UWP Binding image from local folders - c#

My app takes a photo using the Camera and saves it like this C:\Users...\Pictures\file.PNG. I have an object with string "C:\Users\...\Pictures\file.PNG" and binding set to that string, but it does not load the Image. If i place the image to Assets and set the string to "Assets\file.png" it works. Is it possible to bind outside of Assets?

First of all you need to realize that you do not have access to file system as e.g. in Win32 apps. So the full path in UWP app is not relevant anymore. Please take a look on this link to explain it more and nice one here.
I assume you're using Image control to display image. Something like:
MainPage.xaml
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="MainPage_OnLoaded">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Image Name="Img1" />
</Grid>
</Page>
MainPage.xaml.cs
private async void MainPage_OnLoaded(object sender, RoutedEventArgs e)
{
var file = await Windows.Storage.KnownFolders.CameraRoll.GetFileAsync("p1.png");
using (var imgStream = await file.OpenStreamForReadAsync())
{
var bitmapImg = new BitmapImage();
bitmapImg.SetSource(imgStream.AsRandomAccessStream());
Img1.Height = bitmapImg.PixelHeight; //Need to take care of proper image-scaling here
Img1.Width = bitmapImg.PixelWidth; //Need to take care of proper image-scaling here
Img1.Source = bitmapImg;
}
}
When you understand file-access concept files in UWP, you can take closer look on built-in camera control support. There's also example how to directly access captured image without hassling with file names.

Related

WPF can't display image properly

Yesterday I create a project in my disk D partition and I found the images I put into project can't be displayed well. XAML code below is very simple:
<Window x:Class="WpfImageTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfImageTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Image Width="300" Height="300" Source="/Resources/Images/Chen.png"/>
</Grid>
</Window>
You can see I write a relative path for Image control's Source property and when I run the application it shows nothing on the interface.But magically I copy all the files into the root of my C partition or D partition of my physical disk and rebuild the project, the application runs properly. This proplem troubles me almost all day , can anyone explain why this thing happens?
The original location of my project is D:\Programming\C#\Practice\WpfImageTest and I have already set all images build property to Copy all the time and Content.
Select your image file in your Solution Browser and set its Build Action to Resource as on image below.

WPF image not rendering after setting source

I am attempting to set the image source in an effort to ultimately pull corporate standard images from what will be a DLL reference.
For testing and to ensure the proper syntax of the Uri, the image was loaded locally to a test project and the source was hard coded in the XAML.
<Image Name="imgTest" Source="pack://application:,,,/test2;component/Dictionaries/bricks.png"/>
The hardcoded value of imgTest.Source was viewed in debug mode and reads:
imgTest.Source = "pack://application:,,,/test2;component/Dictionaries/bricks.png"
Next, the source for the image was set in code.
BitmapImage imageUri = new BitmapImage();
imageUri.BeginInit();
var imageSource = new Uri(#"pack://application:,,,/" + Assembly.GetExecutingAssembly().GetName().Name + ";component/" + "Dictionaries/bricks.png", UriKind.Absolute);
imageUri.UriSource = imageSource;
imageUri.EndInit();
imgCopy.Source = imageUri;
The softcoded value of imgTest.Source was viewed in debug mode and reads:
imgTest.Source = "pack://application:,,,/test2;component/Dictionaries/bricks.png"
Both the hard coded and soft coded values are identical however the image does not render with the soft coded configuration.
Updates of the 'Build Action' property for the image have been attempted with Embedded Resource, Content, and Resource in combination with each of the three options available for the 'Copy to Output Directory' property.
Any wisdom on this issue is greatly appreciated.
Edit # 1
A side-by-side comparison where I copied the Source property to the soft coded image yields no image being displayed while the hard coded image does yet debug shows identical Source values. XAML and C# code shown.
<Image Name="imgCopy_Soft" />
<Image Name="imgCopy_Hard" Source="Dictionaries/bricks.png" />
imgCopy_Soft.Source = imgCopy_Hard.Source;
Edit # 2 Here is the full XAML
<UserControl x:Class="test2.ucConfigurator"
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"
xmlns:local="clr-namespace:test2"
mc:Ignorable="d" Height="439.5" Width="400">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<Image Name="imgCopy_Soft" Grid.Column="0" />
<Image Name="imgCopy_Hard" Grid.Column="1" Source="pack://application:,,,/test2;component/Dictionaries/bricks.png" />
</Grid>
</Grid>
</UserControl>
And the code behind it:
namespace test2
{
public partial class ucConfigurator : UserControl
{
public ucConfigurator()
{
InitializeComponent();
}
public void Initialize()
{
BitmapImage imageUri = new BitmapImage();
imageUri.BeginInit();
var imageSource = new Uri(#"pack://application:,,,/" + Assembly.GetExecutingAssembly().GetName().Name + ";component/" + "Dictionaries/bricks.png", UriKind.Absolute);
imageUri.UriSource = imageSource;
imageUri.EndInit();
imgCopy_Soft.Source = imageUri;
imgCopy_Soft.Source = imgCopy_Hard.Source;
}
}
}
First, the DLL needs to be added as a References in Visual Studio:
I created a library project inside the same solution and named it _ImageLibrary. I then checked the box for it so it will be added to my project like so:
Inside the DLL, I set the image to this:
I have an image called awesome-cat.jpg. It is inside of a project directory called Resources.
I can then access it like so:
<Image Source="pack://application:,,,/ImageLibrary;component/Resources/awesome-cat.jpg"/>
REMEMBER!!! The portion of the XAML above shows the ASSEMBLY NAME and NOT the project name!!!! My assembly is ImageLibrary.dll.
Now if you HAVE the DLL as a loose file, just add it to your project and then reference that in References using the Browse feature.
It should be noted, this will only work if the DLL is shipped along side your exe. If you want to embed the DLL, then that is a whole different ball game and I can show you how to do that if you ask a separate question for it.

Adding xaml elements for VLC player to WPF application

I am making a video game in C# WPF. I have a huge number of MediaElements, that run mp3 and mp4 files when needed. Recently I read that there is a license fee for just using those file formats, and decided to convert them to ogg and ogv formats.
Just to be sure you understand: I am not trying to make my own video player. I only need a way to run relevant files, at the correct stages of my game.
I found some information on the web, and now trying to make a small test app, that just runs a video on start.
I installed those NuGet plugins (didn't know which one is needed):
Meta.Vlc, Vlc.DotNet.Core, Vlc.DotNet.Core.Interops, Vlc.DotNet.Wpf
That's my xaml file:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:Vlc.DotNet.Wpf;assembly=Vlc.DotNet.Wpf"
xmlns:local="clr-namespace:Test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<MediaElement x:Name="movTest" Panel.ZIndex="1" HorizontalAlignment="Left" Height="319" Margin="10,0,0,0" VerticalAlignment="Top" Width="507" LoadedBehavior="Manual" Source="Resources/VideoFallingFromTable.ogv"/>
<wpf:VlcControl x:Name="movTest2" Panel.ZIndex="2" />
</Grid>
Now, I see that there is no "Source" for wpf:VlcControl.
Si, I tried to load the source from MediaElement.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
movTest2.MediaPlayer.Play(movTest.Source);
}
But I get just black window and no sound. I guess I am doing something wrong.
Can you help me learn to run VLC player in WPF?
Thank you,
Evgenie
UPDATE:
I tried following code:
VlcControl thisVlcControl = new VlcControl();
Uri src = new Uri(movTest.Source.ToString(), UriKind.RelativeOrAbsolute);
thisVlcControl.MediaPlayer.Play(src);
For some reason, it worked with mp4 file, but not with ogv.

How to set relative uri from xaml in wpf?

So I am wondering where the relative uri should be set relative to. I had assumed it was the main project.
I have the image stored under a folder images. The images folder is directly under the project DaedalusGraphViewer under the solution which also has the same name (DaedalusGraphViewer).
I had assumed that the relative uri was relative to the project, but I don't seem to be having any luck. Alternative ideas such as doing it from code behind are also welcome. I have done it from code behind before so I can probably figure that out since I will be able to debug it better there, but I would prefer to just do it in xaml.
I am using
<ResourceDictionary Source="DaedalusGraphViewer/ResourceDictionaries/GraphViewerBrushes.xaml" />
to do the same thing elsewhere, so I don't see what I'm doing wrong.
<Button
Height="50"
VerticalAlignment="Top"
>
<Image Width="50" Height="50" Source="Images/zoominbutton.bmp" Stretch="Fill"/>
</Button>
edit: still no luck, not sure what I'm doing wrong.
i've revised the code to use a much smaller test case.
ideally i would like to be able to set the image path from xaml, but for now i'm trying code behind just to see if I can figure out anything that will make it work.
<Window
x:Class="TestApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
Loaded="Window_Loaded"
>
<Canvas x:Name="MainCanvas">
<!--<Image x:Name="ImageSource2" Width="50" Height="50" Source="/DaedalusGraphViewer;component/images.jpg" Stretch="Fill"/>-->
<!--<Image x:Name="imagetest" Stretch="Fill" Width="50">
<Image.Source>
<BitmapImage
DecodePixelWidth="200"
UriSource="/Images/images.jpg"/>
</Image.Source>
</Image>-->
<!--<Image Width="50" Source="../../Images/images.jpg" Stretch="Fill"/>-->
</Canvas>
</Window>
namespace TestApp
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Image i1 = new Image();
Uri relativeuri = new Uri("/DaedalusGraphViewer;component/images.jpg", UriKind.Relative);
BitmapImage bmi = new BitmapImage(relativeuri);
i1.Source = bmi;
MainCanvas.Children.Add(i1);
}
}
}
My goal for now is just to display an image on the main canvas. When do I need to use an absolute uri and when can I use a relative Uri. I have read lots of examples of xaml using relative uris so I thought that would be possible.
Replace YOURAPPNAME
<Image Width="50" Height="50" Source="/YOURAPPNAME;component/Images/zoominbutton.bmp" Stretch="Fill"/>
I got it to work using "pack://application:,,,/images.jpg" as the source. However, I'm still confused as to why I can't get a relative pack uri to work like this:
http://msdn.microsoft.com/en-us/library/aa970069.aspx
I thought I could just use a source = "/images.jpg"
I read elsewhere that there is a default string to uri converter that converts the relative uri to an absolute uri based on the assembly being built.
anyway if anyone knows how to get the relative pack uri to work or why it doesn't work, please let me know.
I also got ebattulga's answer to work, so I'm selecting it as the right answer. However, I would like to understand a bit better why the relative pack uri from the pack uri site doesn't work.
ps - It doesn't appear to work with the image set to content. I got it working with the image build type set to resource
ps2- I haven't been able to get the same code to work with .bmp extension images. Not sure what is going on.

Animated Gifs with Imagetools, in WP7 c#

Well, This has been solved. I don't know if it was a glitch on my end or if ImageTools was just a pain to set up accordingly. Thank you for the answers everyone, and they very likely all work. The once I marked as answered does indeed work, BUT HERE IS HOW:
(Credits go to Patrick for sticking with this, and his code is used as
noted below.)
(Also, big thanks to everyone else too who submitted something. Sorry
if my noobness scared you all away)
To get an animated Gif to work in your wp7 7.1 app, do these steps:
1) Download ImageTools (I used latest version at the time (0.3)) http://imagetools.codeplex.com/downloads/get/156530
2) Unstuff the file, and in the "Bin > Phone" folder just throw ALL* the dll file extensions into your wp7 app folder. The other files (xml/pdb) don't need to be added. (*this step is extra work, and we will be removing these extra dlls later on, but hell it'll save a headache.)
3) Add the references to your wp7 app in the Solution Explorer window > References folder drop down. To do that, right click the References folder, click "Add Reference" and browse to the dll files. Repeat this process. (Referencing all those dlls is 1 minute of the extra 2 mins of work ultimately, but you shouldn't get any errors when compiling)
4) Now on the xaml page you want to add the image to, add this at the top in your header code:
xmlns:it="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls"
xmlns:vm="clr-namespace:GifViewer.ViewModels"
NOTICE: Change "GifViewer" to your application name.
5) On that same page, just below it, add in this code:
<phone:PhoneApplicationPage.DataContext>
<vm:MainViewModel/>
</phone:PhoneApplicationPage.DataContext>
<Grid x:Name="LayoutRoot" Background="Transparent">
<it:AnimatedImage Source="{Binding AnimationImage}" />
</Grid>
NOTICE: Doesn't have to be a grid. Doesn't have to be in anything at all. It can stand alone.
6) The accepted answer has a folder in the app called "ViewModels" and in it is a custom class titled "MainViewModel" So in the solution explorer or in the desktop, add a folder called ViewModels and make a c# class page titled MainViewModel. Move that into that folder, and refresh the solution explorer. If you cannot see the file, you need to click the "Show all files" button just under the Solution Explorer Header.
7) Using the accepted answer below, in the "MainViewModel.cs" class page, add the following just below the others:
using ImageTools;
using ImageTools.Controls;
using ImageTools.IO;
using ImageTools.IO.Gif;
8) The accepted answer uses this code. Change "GifViewer" to your application name when copying this code, and also change the Uri location of the gif. In my example, I have a folder named "Gif" and in it is "explosion.gif". Build Action can be kept as Resource by default.
namespace GifViewer.ViewModels {
public class MainViewModel : DependencyObject {
public MainViewModel() {
Decoders.AddDecoder<GifDecoder>();
Uri uri = new Uri("Gif/explosion.gif", UriKind.Relative);
ExtendedImage image = new ExtendedImage();
// either of these two method work.
// Just remove the first / to switch
//*
image.LoadingCompleted +=
(o, e) => Dispatcher.BeginInvoke(() => AnimationImage = image);
image.UriSource = uri;
/*/
Stream stream = Application.GetResourceStream(uri).Stream;
GifDecoder decoder = new GifDecoder();
decoder.Decode(image, stream);
AnimationImage = image;
/**/
}
public static readonly DependencyProperty AnimationImageProperty =
DependencyProperty.Register("AnimationImage",
typeof(ExtendedImage),
typeof(MainViewModel),
new PropertyMetadata(default(ExtendedImage)));
public ExtendedImage AnimationImage {
get { return (ExtendedImage)GetValue(AnimationImageProperty); }
set { SetValue(AnimationImageProperty, value); }
}
}
}
Go ahead and compile. You might get a runtime error indicating that
couldn't load, but running the application should get rid of it.
Your gif should now play.
9) Start removing the EXTRA dll references which aren't needed (the other minute of the 2 mins of extra work). Basically, all you want referenced is:
ImageTools
ImageTools.Controls
ImageRools.IO.Gif
ImageTools.Controls might not even be needed, but the file size is like 25kb and honestly I couldn't get the gif to show if I removed it.
There you go!
Original Question I asked
I am having the worst headache trying to get my animated gif to play in my WP7 app. I simply cannot connect the dots to make this happen, despite having imagetools and viewing the current "solutions" on stackoverflow/the web.
My problem is outlined below, but for reference I have looked at:
Display GIF in a WP7 application with Silverlight
and http://blog.naviso.fr/wordpress/?p=733
So how does one actually set this blasted thing up to display animated gifs in a wp7 app!? Question in specific -- Is this the correct code to get my animated gif to appear? If not, what below needs to be fixed?
My animated gif file location on the phone (NOT from internet):
Gif/explosion.gif
Main Xaml page:
xmlns:imagetools="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls"
....
<phone:PhoneApplicationPage.Resources>
<imagetools:ImageConverter x:Key="ImageConverter" />
</phone:PhoneApplicationPage.Resources>
....
<imagetools:AnimatedImage x:Name="animationgif" Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}" />
and the code behind for the xaml page:
public partial class MainPage : PhoneApplicationPage
{
using ImageTools;
using ImageTools.Controls;
using ImageTools.IO.Gif;
public MainPage()
{
InitializeComponent();
ImageTools.IO.Decoders.AddDecoder<ImageTools.IO.Gif.GifDecoder>();
}
public void eventtofiretoshowexplosion_gif(object sender, MouseButtonEventArgs e)
{
// A main problem -- this code doesn't work by itself, as what is the ImageSource!?
// It cannot be used as a variable it says.
// animationgif.ImageSource does not work at all (not a method).
ImageSource = new Uri("http://mysite/my.gif", UriKind.Absolute);
}
}
This has been bugging me for the past few hours, and I really could use some help with this. If there is a quick fix to this, please help out and show how it is done instead of guiding me to a page. I've seen FAR too many pages about this, and while each one claims to work, it just cannot in my app.
It seems the Build Action of your image is incorrect, so the application can't "find" the resource.
You have two options. Either set the build action to content, or set it as resource and specify "copy if newer".
Open your solution explorer
Open your properties window
Click on your image
Set Build action to Resource and Copy to output directory Copy if newer
Further reading: Resources in WPF – I (Binary Resources)
I put together a small example using a viewmodel which seems to work given the above resource "requirement". I hope you might find it useful. The viewmodel class is in a folder called ViewModels.
using System;
using System.IO;
using System.Windows;
using ImageTools;
using ImageTools.IO;
using ImageTools.IO.Gif;
namespace GifViewer.ViewModels {
public class MainViewModel : DependencyObject {
public MainViewModel() {
Decoders.AddDecoder<GifDecoder>();
Uri uri = new Uri("Gif/explosion.gif", UriKind.Relative);
ExtendedImage image = new ExtendedImage();
// either of these two method work.
// Just remove the first / to switch
//*
image.LoadingCompleted +=
(o, e) => Dispatcher.BeginInvoke(() => AnimationImage = image);
image.UriSource = uri;
/*/
Stream stream = Application.GetResourceStream(uri).Stream;
GifDecoder decoder = new GifDecoder();
decoder.Decode(image, stream);
AnimationImage = image;
/**/
}
public static readonly DependencyProperty AnimationImageProperty =
DependencyProperty.Register("AnimationImage",
typeof(ExtendedImage),
typeof(MainViewModel),
new PropertyMetadata(default(ExtendedImage)));
public ExtendedImage AnimationImage {
get { return (ExtendedImage)GetValue(AnimationImageProperty); }
set { SetValue(AnimationImageProperty, value); }
}
}
}
and the xaml
<phone:PhoneApplicationPage
x:Class="GifViewer.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:it="clr-namespace:ImageTools.Controls;assembly=ImageTools.Controls"
xmlns:vm="clr-namespace:GifViewer.ViewModels"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.DataContext>
<vm:MainViewModel/>
</phone:PhoneApplicationPage.DataContext>
<Grid x:Name="LayoutRoot" Background="Transparent">
<it:AnimatedImage Source="{Binding AnimationImage}" />
</Grid>
</phone:PhoneApplicationPage>
When using AnimatedImage your source binding has to return ExtendedImage. ExtendedImage class is basically the "BitmapImage" equivalent of the normal Image control.

Categories