Decoding a jpg in the background in WP7 - c#

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.

Related

Advice on image storing

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

C#: Capturing still images, from multiple (USB )cameras

I need some guidance.
I have to create a simple program, that captures still images every n Seconds, from 4 cameras, attached with USB.
My problem is, that the cameras cannot be "open" at the same time, as it will exceed the USB Bus bandwidth, so I will have to cycle between them.
How to do this, i'm not so sure about.
I've tried using EmguCV, which is a .NET wrapper for OpenCV, but I'm having trouble controlling the quality of my images. I can capture 1280x720, as intended, but it seems like they are just scaled up, and all the image files are around 200kb.
Any ideas on how to do this, properly?
I hate to answer my own question, but this is how I have ended up doing it.
I continued with EmguCV. The images are not very large (file size), but it seems like that is not an issue. They are saving with 96 dpi, and it looks pretty good.
I cycle through the attached cameras, by initiating the camera, taking a snapshot and then releasing the camera again.
It's not as fast as I had hoped, but it works. In average, there is 2 seconds between each image.

Why my images are taking too much time to load?

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

Images from a video show subtle differences when processed on different computers

I have a small video clip that I've run through my video to image software and noticed that the images come out different. Both set of images are identical in which they are cut at 1 second segments. Where they vary is one of the images seem to be brighter then the other set. I'm trying to think what can cause this subtle difference, but I'm at a loss.
I thought that maybe because the hardware is different that would cause this, but I'm not doing anything on the GPU. I also thought that it could be the codec being used, but if the video is encoded the same way using the same codec and information then would decoding really effect it in this way?
Below is a list of what the program is:
Takes a video and saves it out as 1 second images
Uses DirectX in C# to load in a video and saves out the texture.
Video is encoded using MPEG-4 similar compression
I understand that this may not be much information to go off of, but I am at a loss of where I can look.
Any advice is greatly appreciated.
I'd say that images are not actually different. It is unlikely that MPEG-4 decoding uses any GPU resources. Well, it's possible to hardware decode MPEG-4 Part 10, but it's subject to certain conditions too. Far more likely, the effect is due to on of the reasons below (or both):
if you show the picture up within video streaming context, or as you mentioned textures in use - the images might be appearing from YUV surfaces which video hardware is managing differently from regular stuff like desktop, and video hardware might be having a different set of brightness/contrast/gamma controls for those, which result in different presentation
you have different codecs/decoders installed and they decode video with certain differences, such as with post-processing; with all the same encoded video, decoded presentation might be a bit different

Is there a more performant alternative to ImageList.Images.Add?

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());

Categories