I'm working on an app which loads images from a chosen folder to a gridView.
when I use SetSource to set the BitmapImage source I receive an error "insufficient memory" after loading some of the images.
when I use the constructor with a Uri path it works fine. but it will only display images from the projects directory.
StorageFolder folder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(RecentToken);
StorageFile file = await folder.GetFileAsync(path);
IRandomAccessStream stream = await file.OpenReadAsync();
image = new BitmapImage(new Uri(file.Path));//loads only within project directory
image.SetSource(stream);//causes insufficient memory
stream.Dispose();
Found the solution!
I set the BitmaPimage's DecodePixelHeight to the size of the Displayed image and it works fine now!
Related
I want to edit a video file with UWP media composition and then save it back to the existing file. However, when I select the same file the rendering doesn't work because the data stream get corrupt.
As a workaround I render the video to a temporary file and move it then to the existing location:
// Create temp file
var tempFolder = ApplicationData.Current.TemporaryFolder;
StorageFile tempFile = await tempFolder.CreateFileAsync(Guid.NewGuid().ToString(), CreationCollisionOption.ReplaceExisting);
// Render video to temp file so stream get not corrupted
mediaComposition.RenderToFileAsync(tempFile, MediaTrimmingPreference.Precise);
// If rendering completed move temp file to existing video
await tempFile.MoveAndReplaceAsync(existingFile);
My workaround works fine except that the temporary folder is on my local disk and when I edit large video files on my external disk I can run out of storage on my local disk.
Is there another possibility to override an existing file with RenderToFileAsync()?
Update:
As suggested in the comments I set the file size to zero with the following code but then I get a FileNotFoundException:
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
stream.Size = 0;
stream.Dispose();
I have an image in the Assets folder of my UWP project ("Assets/Nophoto.jpg") that I would like to save as a StorageFile in the app's local folder.
The only way I have seen to save an image in a StorageFile is with the FilePicker.
FileOpenPicker FilePicker = new FileOpenPicker();
FilePicker.FileTypeFilter.Add(".jpeg");
FilePicker.FileTypeFilter.Add(".png");
FilePicker.FileTypeFilter.Add(".jpg");
FilePicker.ViewMode = PickerViewMode.Thumbnail;
FilePicker.CommitButtonText = "Picture";
FilePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
PictureFile = await FilePicker.PickSingleFileAsync();
How would I go about storing an image file(.jpeg, .png, .bmp, ect..) in a StorageFile
Answering your question:
I have an image in the Assets folder of my UWP project ("Assets/Nophoto.jpg") that I would like to save as a StorageFile in the app's local folder.
You can do it for example like this - getting file via Uri (note that it can also be accessed via InstaledLocation folder):
StorageFile sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Nophoto.jpg"));
await sourceFile.CopyAsync(ApplicationData.Current.LocalFolder);
Once you have a StorageFile (no matter if obtained via picker/from installation folder/other) then you can copy it to other StorageFolder. If you have an image via a stream or pixel buffer, then you can create a file and write to it by using a stream.
I am downloading and saving an image from internet, image gets saved into Saved Pictures folder.
Heres part of the code:
var imagefile = await KnownFolders.SavedPictures.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
var filestream = await imagefile.OpenAsync(FileAccessMode.ReadWrite);
var writer = new DataWriter(filestream.GetOutputStreamAt(0));
writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
I can see images there if I navigate to the folder via pc, they can be opened and seem to work just fine.
What am I missing?
I have images that is not located in resources but on the disk. The folder is relative to application. I used:
Overview_Picture.Source = new BitmapImage(new Uri(String.Format("file:///{0}/../MyImages /myim.jpg", Directory.GetCurrentDirectory())));
Overview_Picture.Source = new BitmapImage(uriSource);
But those type of code created many problems and messed up GetCurrentDirectory returns that sometime ok and some times not.
So, MyImages folder is located next to Debug folder, how can I use them images there and not as I done, In some other more right way?
As mentioned oftentimes here on SO, the GetCurrentDirectory method does by definition not always return the directory your assembly resides in, but the current working directory. There is a big difference between the two.
What you need is the current assembly folder (and the parent of that). Also, I'm not sure whether it is wanted that the pictures are one folder above the installation folder (which is basically what you're saying when you say they are one level above the Debug folder - in real life that would be one folder above the folder the application is installed to).
Use the following:
string currentAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string currentAssemblyParentPath = Path.GetDirectoryName(currentAssemblyPath);
Overview_Picture.Source = new BitmapImage(new Uri(String.Format("file:///{0}/MyImages/myim.jpg", currentAssemblyParentPath)));
Also, there's a stray space after MyImages, which I removed.
An alternative to constructing an absolute Uri from a relative file path would be to just open a FileStream from the relative path, and assign that to the BitmapImage's StreamSource property. Note however that you also have to set BitmapCacheOption.OnLoad when you want to close the stream right after initializing the BitmapImage.
var bitmap = new BitmapImage();
using (var stream = new FileStream("../MyImages/myim.jpg", FileMode.Open))
{
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze(); // optional
}
Overview_Picture.Source = bitmap;
I'm writing a windows phone 8 app and I would like to let users use images saved to their skydrive in my app. The piece of code I'm having trouble with (I believe) is below.
StorageFile thefile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("b4b.png", CreationCollisionOption.ReplaceExisting);
Uri theuri = new Uri("ms-appdata:///local/b4b.png");
var thething = await client.BackgroundDownloadAsync(filepath, theuri); <--- line where program crashes
BitmapImage src = new BitmapImage();
src.SetSource((Stream)await thefile.OpenReadAsync());
WriteableBitmap image = new WriteableBitmap(src);
all the signing in and authentication stuff that the user needs to do is already done by this point and works as expected. When my program reaches the marked line, it suddenly crashes. The errors I receive are...
A first chance exception of type 'System.ArgumentException' occurred in Microsoft.Live.DLL
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.ni.dll
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.ni.dll
'TaskHost.exe' (CLR C:\windows\system32\coreclr.dll: Silverlight AppDomain): Loaded 'C:\windows\system32\en-US\mscorlib.debug.resources.dll'. Module was built without symbols.
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.ni.dll
Does anyone know how to fix this?
I inserted breakpoints to trace the program and it appears that the storage file is being made and the uri is correct, but when I try to download the file to it, the program gives me the error. I confirmed the filepath for the file on skydrive is also correct. If I try to use DownloadAsync() instead it appears to work but then the program crashes when I try to use the stream obtained from the skydrive file instead and gives the same error.
Any ideas? Because I can't figure out what could be wrong.
The file being downloaded is a png image.
EDIT: Solution Found
After some more research I found out that when you download files from skydrive a call for a files id...
filepath = result.id;
as above that does not give you the contents of the file. I didn't check what it was obtaining but I'd assume it was probably the metadata. To obtain the actual contents of the file you must add "/contents".
The correct path would then be
filepath = result.id + "/contents";
I edited my code as shown below and it now works perfectly.
StorageFile thefile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("b4b.png", CreationCollisionOption.ReplaceExisting);
Uri theuri = new Uri("ms-appdata:///local/b4b.png", UriKind.Absolute);
var thething = await client.DownloadAsync(filepath + "/content");
Stream stream = thething.Stream;
stream.Seek(0, SeekOrigin.Begin);
BitmapImage src = new BitmapImage();
src.SetSource(stream);
Hope this helps anyone having the same problem as I was!
From the #deboxturtle's update, as an answer for search sake:
After some more research I found out that when you download files from skydrive a call for a files id...
filepath = result.id;
as above that does not give you the contents of the file, you get file metadata as json. To obtain the actual contents of the file you must add /content to the id.
The correct path would then be
filepath = result.id + "/content";
I edited my code as shown below and it now works perfectly.
var filepath = result.id + "/content";
StorageFile thefile = await ApplicationData.Current.LocalFolder.CreateFileAsync(
"b4b.png", CreationCollisionOption.ReplaceExisting);
var thething = await client.DownloadAsync(filepath);
Stream stream = thething.Stream;
stream.Seek(0, SeekOrigin.Begin);
BitmapImage src = new BitmapImage();
src.SetSource(stream);