Is there any way to fetch images as strings to UWP applications?
Im trying to get my images from my database (ms-sql server) and showing them in my UWP application. I only got the names out right now, no images.. is there any way to display the "imagefile" in a image source tag in xaml?
My api
XAML code:
<Grid>
<ListBox x:Name="lstImages">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"></TextBlock>
<Image Source="{Binding ImageFile}"></Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Page>
XAML.cs
public ObservableCollection<Games> gamesList { get; set; } = new ObservableCollection<Games>();
public MainPage()
{
this.InitializeComponent();
LoadImages();
}
internal async System.Threading.Tasks.Task LoadImages()
{
HttpClient httpClient = new HttpClient();
string apiURL = #"http://localhost:65143/api/Games";
HttpResponseMessage response = await httpClient.GetAsync(new Uri(apiURL));
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
gamesList = JsonConvert.DeserializeObject<ObservableCollection<Games>>(content);
lstImages.ItemsSource = gamesList;
}
}
}
Is there any way to fetch images as strings to UWP applications?
Yes, there is a way to do this. Based on your description, you've got the path of the image that you want to show. Then what you need is just to open the image file as a stream and set the stream as the source of the BitmapImage object using BitmapSource.SetSourceAsync() Method.
First of all, you have to add the Document capability in the manifest file to get permission to access the Document Library. More details here: File access permissions.
Like this:
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="documentsLibrary"/>
</Capabilities>
Then you could get the image file and open it as stream.
Here is the sample code that you could refer to:
StorageFolder folder = await KnownFolders.DocumentsLibrary.GetFolderAsync("uwpAppPics");
StorageFile file = await folder.GetFileAsync("london.png");
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
//MyImage is the image control
MyImage.Source = bitmapImage;
}
Related
I have trouble with image loading (just on this pc, on other one its ok)
Im tried a few ways to put image
<Image
MinWidth="190"
Stretch="Fill"
MinHeight="190"
Source="{Binding ImagePath, Converter={StaticResource UriToImageConverter}}">
<!--If you use my way in answer you need replace Source like this-->
Source="{Binding Image}"><!--Bitmapimage property in model-->
</Image>
Its works only if I put path like 'ms-appx' but in target I need use 'Binding' its works on other pc witout any troubles but here I have "transparent" picture on a page
Ok, I just put images to StorageFile's and copied it to local folder and take it from there and put into my Model's property
Before:
this.collageimages = await OpenPicker.PickMultipleFilesAsync();
for (var i = 0; i < this.collageimages.Count; i++)
{
var stream = await collageimages[i].OpenAsync(FileAccessMode.Read);
this.image = new BitmapImage();
await this.image.SetSourceAsync(stream);
}
After:
this.collageimages = await OpenPicker.PickMultipleFilesAsync();
for (var i = 0; i < this.collageimages.Count; i++)
{
await this.collageimages[i].CopyAsync(ApplicationData.Current.LocalFolder, "collageImage_"+i+"", NameCollisionOption.ReplaceExisting);
var tempStorage = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appdata:///local/collageImage_"+i+""));
var stream = await tempStorage.OpenAsync(FileAccessMode.Read);
this.image = new BitmapImage();
await this.image.SetSourceAsync(stream);
}
I do not claim to be the best answer if you know a better way, please write it
I'm trying to add image source from Storage Folder. First I capture photo and save it to the Storage Folder
Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
private async void btnPhoto_Click(object sender, RoutedEventArgs e)
{
// Create the file that we're going to save the photo to.
var file = await storageFolder.CreateFileAsync("sample.jpg", CreationCollisionOption.GenerateUniqueName);
// Update the file with the contents of the photograph.
await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), file);
}
At the next Page I should get the photo from cache, but I have an exception, when I'm creating sampleFile
public async void GetImage()
{
string filename = "sample.jpg";
Windows.Storage.StorageFile sampleFile =
await Windows.Storage.KnownFolders.DocumentsLibrary.GetFileAsync(filename); // Here I have exception {"Access is denied.\r\n"} System.UnauthoriziedAccessException
BitmapImage img = new BitmapImage();
img = await LoadImage(sampleFile);
image1.Source = img;
}
private static async Task<BitmapImage> LoadImage(StorageFile file)
{
BitmapImage bitmapImage = new BitmapImage();
FileRandomAccessStream stream = (FileRandomAccessStream)await file.OpenAsync(FileAccessMode.Read);
bitmapImage.SetSource(stream);
return bitmapImage;
}
What I'm doing wrong? And how can I get access to Storage Folder?
You can't access the document library unless the user allows you to do that. You can specify document library access in the manifest, but only for certain files, and such app will probably never be published in the Windows Store unless it REALLY requires that access as stated by Microsoft. As you are using .jpg files you have Pictures library for that, and you can specify it in the manifest and everything will work just fine.
Otherwise you get access by file picker, storing the token to recall it later.
I am working on an application for Windows phone 8.1 in Xamarin with mvvmCross. I need to select multiple images from the phone library and display them. I am using FileOpenPicker.SelectMultipleFilesAndContinue to do so. Now i need to be able to display all these images in the view. One problem is that the minimum amount of images must be 20 and the images could be pretty large.
First i tried making them into byte arrays and used a converter to display them.
public async void SelectFotosCallback(FileOpenPickerContinuationEventArgs args) {
if (args.Files.Count > 0) {
foreach (StorageFile file in args.Files) {
IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
byte[] bytes = null;
using (var reader = new DataReader(fileStream.GetInputStreamAt(0))) {
bytes = new byte[fileStream.Size];
await reader.LoadAsync((uint)fileStream.Size);
reader.ReadBytes(bytes);
}
callback(bytes);
}
}
else {
}
}
This method did seem to work at the first try but as soon as I tried it with 5 images it stopped working. When it was done with the callback the app just quit. No error message or anything. (My guess is an overload in memory.)
After this i found a little solution where i take the byte arrays and make them to Xamarin.Form Images.
public async void SelectFotosCallback(FileOpenPickerContinuationEventArgs args) {
if (args.Files.Count > 0) {
foreach (StorageFile file in args.Files) {
IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
byte[] bytes = null;
using (var reader = new DataReader(fileStream.GetInputStreamAt(0))) {
bytes = new byte[fileStream.Size];
await reader.LoadAsync((uint)fileStream.Size);
reader.ReadBytes(bytes);
}
Image image = new Image();
image.Source = ImageSource.FromStream(() => new MemoryStream(bytes));
var iets = image.Source.BindingContext;
callback(image);
}
}
else {
}
This seemed to take care of the problem for the overload in memory. the only other problem now is that i can not seem to find any way the display these images.
<GridView ItemsSource="{Binding SelectedImages}">
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Style="{StaticResource imageListImage}" Source="{Binding Source}"/>
<Button Style="{StaticResource imageListXButton}">
<Button.Background>
<ImageBrush ImageSource="ms-appx:///Resources/XButton.png"/>
</Button.Background>
</Button>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
I try to display them with a simple binding. I have not found any way that would work. Does anyone know a way to display these Images and if not what would be the best alternative to use the bytes without using too much memory.
After some deep digging I was able to find the answer. It was a lot simpeler than I thought. I started working with the decodepixel from the BitmapImage. Using a coneverter I set the values.
public object Convert(object value, Type targetType, object parameter, string language) {
BitmapImage image = (BitmapImage)value;
image.DecodePixelType = DecodePixelType.Logical;
if (image.PixelHeight >= image.PixelWidth) {
image.DecodePixelHeight = 100;
}
else {
image.DecodePixelWidth = 100;
}
return image;
}
The weird thing was that it did work some of the time. But for some reason it didn't work on all the image and it sometimes even threw them away.
But after a lot of testing i finally found what I was looking for.
BitmapImage bitmap = new BitmapImage();
BitmapImage temp = new BitmapImage();
bitmap.DecodePixelType = DecodePixelType.Logical;
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) {
IRandomAccessStream secondStream = fileStream.CloneStream();
BitmapImage temp = new BitmapImage();
temp.SetSource(fileStream);
if (temp.PixelHeight >= temp.PixelWidth) {
bitmap.DecodePixelHeight = 150;
}
else {
bitmap.DecodePixelWidth = 150;
}
bitmap.SetSource(secondStream);
}
For some reason setting the decodepixel after setting the source makes it inconsitent but setting these values before setting the source actually crops the image right away.
This method works perfectly and completely resolves my outofmemory problem
I'm doing this way:
using Windows.Storage;
using Windows.UI.Xaml.Media.Imaging;
...
private async void LoadFiles()
{
StorageFolder folder = KnownFolders.SavedPictures;
IReadOnlyList<StorageFile> list = await folder.GetFilesAsync();
var images = new List<BitmapImage>();
if (list != null)
{
foreach (StorageFile file in list)
{
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(stream);
images.Add(bitmapImage);
}
}
flipView.ItemsSource = images;
}
xaml
<FlipView x:Name="flipView"
SelectionChanged="flipView_SelectionChanged">
<FlipView.ItemTemplate>
<DataTemplate>
<Image Stretch="UniformToFill" Source="{Binding}" />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
I get this exception
A first chance exception of type 'System.Exception' occurred in
mscorlib.ni.dll
Additional information: The component cannot be found. (Exception from
HRESULT: 0x88982F50)
at this line
await bitmapImage.SetSourceAsync(stream);
Please, what is the problem?
The program works but the problem was corrupted jpg files.
They had a 0 bytes size so the stream could not be created.
Check if this variable has been created or if it's full of data.
I am trying to develop a simple Windows 8 Metro app which simply downloads an image file from a given URL (say http://sample.com/foo.jpg) and then save it to Pictures Library.
I have an image control in the UI to display the downloaded image.
I'm also facing difficulty in setting the image source for the image control to the newly downloaded image (actually I'm not even able to download it).
Also, is it possible to store the image file in a particular folder in the Pictures library (if it doesn't exist, then the app should create it)?
I'm really stuck here.
Please help me.
Here's some rough code that I believe accomplishes what you want. It assumes you have two image controls (Image1 and Image2) and that you have the Pictures Library capability checked in the manifest. Take a look at the XAML images sample as well
Uri uri = new Uri("http://www.picsimages.net/photo/lebron-james/lebron-james_1312647633.jpg");
var fileName = Guid.NewGuid().ToString() + ".jpg";
// download pic
var bitmapImage = new BitmapImage();
var httpClient = new HttpClient();
var httpResponse = await httpClient.GetAsync(uri);
byte[] b = await httpResponse.Content.ReadAsByteArrayAsync();
// create a new in memory stream and datawriter
using (var stream = new InMemoryRandomAccessStream())
{
using (DataWriter dw = new DataWriter(stream))
{
// write the raw bytes and store
dw.WriteBytes(b);
await dw.StoreAsync();
// set the image source
stream.Seek(0);
bitmapImage.SetSource(stream);
// set image in first control
Image1.Source = bitmapImage;
// write to pictures library
var storageFile = await KnownFolders.PicturesLibrary.CreateFileAsync(
fileName,
CreationCollisionOption.ReplaceExisting);
using (var storageStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
{
await RandomAccessStream.CopyAndCloseAsync(stream.GetInputStreamAt(0), storageStream.GetOutputStreamAt(0));
}
}
}
// read from pictures library
var pictureFile = await KnownFolders.PicturesLibrary.GetFileAsync(fileName);
using ( var pictureStream = await pictureFile.OpenAsync(FileAccessMode.Read) )
{
bitmapImage.SetSource(pictureStream);
}
Image2.Source = bitmapImage;
}