I've read about the LowProfileImageLoader. It will only load the image when the user can see it and will avoid blocking the UI thread.
I added it and tested on my application. All 25 images are from the exact same URL. With the default image it took a little to load but all other images were cached, and the scroll got super fast.
With the LowProfileImageLoader the images were not cached, it was loading 1 by 1 even though it was the exact same image. And when I scrolled down then up it would load the image all over again. And it takes a long time to load them.
Do I have to configure something to keep the images on cache? How do I configure this LowProfileImageLoader?
From what I understood by looking at a windows phone mango video presentation, images are automatically cached without you doing anything.
Video I'm talking about: http://www.wpcentral.com/multitasking-mango-demoed-detail
Related
I'm learning my way around windows forms by making a little app to help clean up a folder on my PC with thousands of images. I'm currently storing the images as a List<FileInfo>. It works fine using
PicBox.Load(ImageFileList[count++].imgFile.FullName);
but that's a bit slow when I only need a second to look at each image.
So the problems are:
How to load the images quickly
How to do so in a folder where one image might be a 25kb png and the next might be a 1GB TIFF
If I open an image from the folder in Windows Photo Viewer and hold the right arrow key, it zips along with blurry images I assume are resized thumbnails and a loading message over them. In Win 10 Photos, it loads non-blurry images faster but hiccups when it hits larger files. Either of those behaviors would be fine for me.
Try to do your things using background tasks :
https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/walkthrough-implementing-a-form-that-uses-a-background-operation?view=netframeworkdesktop-4.8
Maybe this can help too :
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.application.doevents?view=windowsdesktop-6.0
I am currently developing an app that will browse(and more things, but this is not relevant) youtube lists. Now whenever I get a video, I display it's corresponding image and show it in a listview (or gridview, again not relevant). Now here is the dilemma: is it better to store the images locally after they are downloaded, or do we download them every time we want them showed, i.e:
this._image = new BitmapImage(new Uri("http://domain.com/content/someImage.jpg"));
You're probably going to want to see what YouTube has to say on the matter; I'm sure it's got something regarding this in its developer API documentation to note their preferred approach to it.
That said, take this as general advice; when you're constantly querying another system, you generally want to limit how annoying you are. Now, YouTube's not going to notice the load of one app, of course, but it's still a good habit to keep. Generally speaking, I'd prefer to split the difference: cache the image based on video ID and hold it for X hours, so if the user pulls up the same video in a search 20 times you didn't request a thumbnail 20 times as well.
That way you keep the result relevant by updating the image every day or two (assuming they searched for the video again).
Edit: Right, app. Mobile. Bandwidth. Godawful data caps. My advice is more important then and you probably want to make it cache for a couple of days to be safe, but have a hard cap of how many video thumbnails you keep at a time so you're not the app taking up 100MB of space on some guy's 8GB phone.
If you want to be super user friendly, throw something in the settings somewhere to let people change the approach to query every time, or cache for a specific time.
It really depends on your usage model. The correct term would be 'cache' image locally 'or' fetch from servers each time you want to show image. If user experience is of higher priority than showing the latest image snapshot of youtube videos (which very likely isn't going to change for same video) - then cache the images locally, with an expiry time. This would be helpful in having a faster user experience and also save some network bandwidth. Caching with expiry would ensure you are not filling up memory on device with too many unnecessary images and also as images get old, they will be less relevant and removed and you can fetch new ones.
Caching policy (the way you determine when an image is not of high importance and how long it should remain) will be an interesting problem and can have significant impact on the user experience
I have a page with a pivot containing about 10 items, each pivot item contains a longlistselector with 30 items each.
Each longlistselector item contains an image.
When I'm browsing the page and I flip to the next pivot item, the app crashes at the 4th pivot item with a memory exception.
Is there anyway to unload undisplayed images in the longlistselector?
i suggest rethinking your app layout, 10 pivot items is a tad too many for normal user navigation, why not have a main page with a longlistselector of "categories" follow by a details page of 30 images.
But if you absolutely have to do it this way, take a look at microsoft's photohub source
I'm using it personally and have no problem loading hundreds of images in a panoramaItem.
Better still if you can afford the time, do a memory profile and look exactly where the bloat is, sometimes it might be some part of your application that is hogging on to the memory.
Last of all, wp itself caches the images automagically, but not everyone likes it this way (i'm sure you don't)
take a look at this:
Image Caching
This is an important one, and MSDN is currently fairly silent about it. If you were ever wondering why your image memory didn't get released after clearing the Source and removing the Image from the tree, you were most likely seeing Image caching in action. This is an intended performance optimization, to avoid (down)loading and decoding the same image over and over again. Instead we keep a cache in memory that we can easily and quickly reuse. This is not to confuse with the browser cache for downloaded files.
While this is a nice and free performance optimization, at times it can blow your memory unnecessarily, especially when you cycle through many images that you will never come back to. Their cache will use up memory for the lifetime of your app. The good news is that you can delete the cache when you decided that you no longer need it:
BitmapImage bitmapImage = image.Source as BitmapImage;
bitmapImage.UriSource = null;
image.Source = null;
Being smart about this can save you quite a bit of memory usage, which is a precious resource on a phone device. In the sample app, go to the "Caching" page and monitor the memory usage as you show/clear the image. Then check the box and try again. You will see a difference of ~3MB in the example case.
You can get the full article here
I have a bunch of apps in the marketplace, and so far I have been able, by changing my functionality or going the extra mile, to work around the issue of being unable to decode a jpg in the background into a WriteableBitmap.
I am finding a situation where I can't think of good ways to "work around" the issue. I need to decode the image I get from MediaLibrary, reduce it's resolution to something managable (800x800), rotate it potentially and save to local storage. By far, the thing that takes the most time (80%) is decoding the bitmap to 800x800 - it takes between 700ms to 1000 ms. A user may add 7-10 images when starting, which translates to ~10 seconds of waiting for the images being added.
I tried doing this lazily, but at some point you need to pay the piper and the app essentially stutters for ~1000ms at that point and the experience is not great.
Is there an alternative I am missing for loading the image in the background somehow?
(Note on why CreateOptions.BackgroundCreation is no good for me: It loads the image into a BitmapImage which is great if you want to just use it, but not so great for what I need to do which is create a copy in Isolated Storage).
Unfortunately something within the constructor of BitmapImage needs to run on the UI thread. :(
I haven't found a workaround but also haven't seen it take anything as long to decode as you're stating.
I have a winforms ImageList which contains 200 256x256 images.
When I add the images, 1 by one, half of the programs time spent on the Add method according to ANTS .NET profiler.
So the program takes 10 secs to launch and 5 is spent there. That is very slow in my opinion.
I implemented the same thing using ImageList.Images.AddRange. The result did not change.
Does anyone know any alternatives or optimizations to solve this? Is the WPF ImageList any faster? Is there a faster winforms ImageList?
EDIT:
foreach (string imageFile in images)
{
imageList.Images.Add(Image.FromFile(imageFile)); // takes pretty much all of program's execution time.
}
Have a look at the album and list views in PhotoSuru, one of Microsoft's WPF sample applications. They have a couple different thumbnail view screens that load pretty quickly (all the images are loaded asynchronously, and only the images necessary are loaded). And there's full source code to get you started if it's what you are looking for.
It not precisely like Picasa (they decided only to show full rows of photos instead of a partially covered row like Picasa), but by implementing your own virtualizing IScrollInfo panel (reasonably straightforward, and Ben Constable has a great series of posts on it), you should be able to get the performance you're looking for and the behaviour you want.
A final note: You might be doing this already (are your images stored as 256x256 pixel images?), but whenever you're trying to display image thumbnails, you'll want to avoid loading the full image. Reading 2 MB+ image files off of the disk just to render an entire screenful of 256x256 pixel thumbnails always has a bigger performance hit than reading an appropriately sized small thumbnail image instead. If you can, cache the thumbnails somewhere (like Windows and Picasa do), or at the very least, try to use the embedded thumbnails in any JPEG files you encounter.
Are you using a ListView for the UI part using that ImageList?
The general solution to these kind of problems is to only load some of the images, because only some of them are shown at a time, and then load the other as needed. ListView has a VirtualMode property for this kind of scenarios.
Loading and adding 200 images at once may be too much to do, you could load the first shown images and then use a background thread to load the others. Have a look at how Win7 display images, it shows some placeholder when you scroll and then, when the image is loaded it shows the real picture. Be warned that this is not a simple thing to do.
try my code here to scale-down your image and make a thumbnail out of it.
Yes it is. Load images to List<Image>. Then call ImageList.Images.AddRange(list).
List<Image> list = new List<Image>();
foreach (string imageFile in images)
{
list.Add(Image.FromFile(imageFile));
}
imageList.Images.AddRange(list.ToArray());