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
Related
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;
}
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 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;
}
In my Windows Store App I save/use files (almost images) in Isolated Storage. When I need to present image i use following:
var file = await folder.GetFileAsync(fileName);
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
obj.Image = new BitmapImage();
await obj.Image.SetSourceAsync(stream);
}
But when I use 3+ images in same page I have lags. I'm looking for faster solution to access Isolated Storage files.
You can try to start with this article Optimize media resources (Windows Store apps using C#/VB/C++ and XAML), and couple more things:
Make sure that if you show them in the ListView / GridView - you have enabled virtualization (you use right ItemsPanel which supports virtualization).
If you just need to load images from local storage - set the binding from Image.Source to to the right URI (ms-appx:/// or ms-appdata:///local/), and Image control will do everything for you.
I don't know how you're opening multiple images, but since all the methods are asynchronous you shouldn't iterate through your files sequentially, but open all of them in parallel.
So instead of doing this (where you're waiting for the previous image to load before starting to load the next one):
foreach (var fileName in fileNames)
{
var file = await folder.GetFileAsync(fileName);
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
obj.Image = new BitmapImage();
await obj.Image.SetSourceAsync(stream);
}
}
You should approach it like this:
// not sure about the type of obj
public async Task<Image> LoadImage(string fileName, dynamic obj)
{
var file = await folder.GetFileAsync(fileName);
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
obj.Image = new BitmapImage();
await obj.Image.SetSourceAsync(stream);
}
}
var tasks = fileNames.Select(f => LoadImage(f, obj)).ToArray();
await Task.WhenAll(tasks);
This will initialize an array of awaitable tasks loading the images and then await all of them at the same time so that they will execute in parallel.
I'm working on creating some animated GIFs in a WinRT app. I've got gif conversion working with multiple frames in the resulting image, but I cannot figure out how to set things like frame delay and repeat behavior.
The GoToNextFrameAsync takes in options which feels like the right place to specify things like that, but I have no idea what to pass in and can't find any documentation on the subject.
public async static void AnimateImages(IEnumerable<StorageFile> files)
{
var outFile = await KnownFolders.PicturesLibrary.CreateFileAsync("test.gif", CreationCollisionOption.ReplaceExisting);
var outStream = await outFile.OpenAsync(FileAccessMode.ReadWrite);
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.GifEncoderId, outStream);
for (int i = 0; i < files.Count(); i++)
{
using (var str = await files.ElementAt(i).OpenAsync(FileAccessMode.Read))
{
var decoder = await BitmapDecoder.CreateAsync(str);
var pixels = await decoder.GetPixelDataAsync();
encoder.SetPixelData(decoder.BitmapPixelFormat, BitmapAlphaMode.Ignore,
decoder.OrientedPixelWidth, decoder.OrientedPixelHeight,
decoder.DpiX, decoder.DpiY,
pixels.DetachPixelData());
if(i < files.Count() -1 )
await encoder.GoToNextFrameAsync();
}
}
await encoder.FlushAsync();
outStream.Dispose();
}
I've been having trouble with this too. It seems that whilst reading properties is OK setting any kind of property on a frame results in an exception. As far as I can tell from here the BitmapEncoders are related to Windows Imaging Components, and as the page for Native WIC Codecs on MSDN states, there are no options for GIFs. It does seem odd though.