Displaying loading progress for Image control in WP7 - silverlight

How do I get loading progress with the percent loaded info when an image is loading?
I have this:
Image image = new Image();
image.Source = new BitmapImage(new Uri("http://somesite.com/someimage.jpg"));
I expected something like this:
image.Loading += RoutedEventHandler(image_Loading);
but I can't find any such event. There is Loaded (not related to loading the source) and ImageOpened (which fires after loading the source is complete and has effected a layout pass).
I know it is possible because I have seen other apps indicate loading progress for images (for example "img news reader"). Is this possible with the standard Image Control, is there a 3rd party control that provides this, or do I have to write my own?

DownloadProgress is the event I was looking for, and it was hiding in the BitmapImage class:
Image image = new Image();
BitmapImage myBitmap = new BitmapImage(new Uri("http://somesite.com/someimage.jpg", UriKind.Absolute));
myBitmap.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(myBitmap_DownloadProgress);
image.Source = myBitmap;

Related

when to use WriteableBitmap and BitmapImage in silverlight

I am trying to display image using BitmapImage for some time and it worked.I have changed the image and it stopped working.
For Bitmapimage I was using this code:
`ms.Seek(0, SeekOrigin.Begin); // ms is memory stream
BitmapImage b = new BitmapImage();
b.SetSource(ms);
image.ImageSource = b;`
I have ran into piece of code where it was checking if the length of the bytes[] ==14400
if(bytes.length == 14400)
{
var bmp = new WriteableBitmap(width, height);
Buffer.BlockCopy(buffer, 0, bmp.Pixels, 0, buffer.Length);
}
I want to know when to use WriteableBitmap and BitmapImage .
From iProgrammer:
Bitmaps are generally implemented as immutable objects. What this means is that once you create a bitmap you can't make any changes to it. You can manipulate bitmaps by creating new versions, which then immediately become immutable....
The WriteableBitmap, as its name suggests, isn't immutable and you can get at its individual pixels and manipulate them as much as you want. This is the ideal way to work when you need dynamic bitmaps.
iProgrammer - WriteableBitmap
From MSDN:
"Use the WriteableBitmap class to update and render a bitmap on a per-frame basis..." MSDN - WriteableBitmap Class
The Examples section of the MSDN article also shows how to update a WritableBitmap image when responding to mouse events. The code in the example erases pixels of the image by setting the pixel's ARGB values to 0 when the mouse's right button is down. The code also shows how to update individual pixels in the image where the mouse's left button is down. Essentially the code shows a rudimentary pixel image editor.
The point, however, is that you can't change image data when using regular bitmap - you have to use WritableBitmap instead. You can, however, render both if you wish.

Image inside stackpanel is not getting displayed

I am creating stackpanel inside the gridview cell dynamically and placing a image control inside stackpanel but on the window only blank space coming, not the image
here is what i am doing
StackPanel Stkpnl = new StackPanel();
Image BgImg = new Image();
BitmapImage Img = new BitmapImage(new Uri(
"Images/cellbg.png", UriKind.Relative));
BgImg.Source = Img ;
Stkpnl.Children.Add(BgImg );
You need to use a Pack URI. See https://stackoverflow.com/a/1651397/486660
If you have a question as to what your Pack URI should look like, then temporarily add an Image control to your WPF page then goto the Source property and click the "..." button and navigate to your image. The property's text box will have the Pack URI in it.
Your code seems to be correct , have you check that image is existing on the folder or the relative path is correct, if you have added this image later to the image folder than you
have to set "Build Action" of a image to "Resource". right click on the image in solution explorer than you can set this property.
you should also check this question
Setting WPF image source in code
StackPanel Stkpnl = new StackPanel();
Image BgImg = new Image();
String packuri = "pack://application:,,,/yourassemblyname;component/cellbg.png";
BgImg.Source = new ImageSourceConverter().ConvertFromString(packuri) as ImageSource;
Stkpnl.Children.Add(BgImg );
PS: To find the assembly name in visual studio 2012 go to "Project" in menu bar -> "setup properties"->Application.

WPF Bitmap performance

I'm trying to understand why my images are not snappy, so I built a sample to test WPF performance. I used a timer to calculate how long my "display images" event handler executed, and used a stop watch to measure how long it took the images to appear on the screen. The bottom line: when displaying 100, 1600, 2500 and 3600 images, WPF took 2, 9, 12 and 16 seconds after my code had finished to display the images on the screen. So I feel helpless: It seems I can't improve my code to make the images appear faster - I need to do something with WPF!
So my question is: What do I need to do differently to make the images display faster?
The test setup is simple:
The window contains a Grid. After the "test" button is clicked, row and column definitions are added.Then an Image is added to each cell of the grid as follows:
var image = new Image();
image.BeginInit();
image.Name = ImageNameFromCell(theRow, theColumn);
image.Stretch = Stretch.None;
image.HorizontalAlignment = HorizontalAlignment.Center;
image.VerticalAlignment = VerticalAlignment.Center;
RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.LowQuality);
image.EndInit();
theGrid.Children.Add(image);
Finally, the Source of each image is set to a bitmap:a gray-scale image already scaled down to the estimated screen size. The bitmap is generated as follows:
var smallerBitmapImage = new BitmapImage();
smallerBitmapImage.BeginInit();
smallerBitmapImage.DecodePixelWidth = (int)(theImageWidth);
smallerBitmapImage.UriSource = theUri;
smallerBitmapImage.CacheOption = BitmapCacheOption.None;
smallerBitmapImage.EndInit();
//BitmapFrame bitmapFrame = BitmapFrame.Create(this.FullPath);
var convertedBitmap = new FormatConvertedBitmap();
convertedBitmap.BeginInit();
convertedBitmap.Source = smallerBitmapImage;
convertedBitmap.DestinationFormat = PixelFormats.Gray16;
convertedBitmap.EndInit();
convertedBitmap.Freeze();
So, I'm at my wits end. The images appear with a noticeable delay, and it seems to be out of my control. What can I do?
What appears to have made the difference is setting the image's cache option to OnLoad
smallerBitmapImage.CacheOption = BitmapCacheOption.OnLoad;
This moved the work to my event handler, so now I can use pre-fetching to do this at the background.
Do you actually see all those images at the same time? If not you can use some ItemsControl with a virtualizing panel so only images in view are displayed. (Speaking of panels, your current setup could also be replaced with an ItemsControl which uses a UniformGrid as panel)
You could also try to write a better decoder, which probably is a wasted effort.

dynamic image download

Can you look at the code below?
Image img = new Image();
BitmapImage bi = new BitmapImage();
bi.UriSource = new Uri("OryxAntelope.jpg", UriKind.Relative);
img.Source = bi;
LayoutRoot.Children.Add(img);
It works fine.
But after I comment last line of code(//LayoutRoot.Children.Add(img);) picture not downloads.
What is the problem of this approach?
Thanks,
Vitaliy
The image is fetched only when it is first displayed. That is occurring after you add it to the layout (and the layout becomes visible).
What are you trying to accomplish? The example does not make it clear what the end result is.
Check out this article. You need to first download the image asynchronously with the WebClient control, and then you will be able to use/display it as you want. What I've done is set up a callback function, since its asynchronous, and you could put your code example in that function so that you don't try to add the image before it's finished downloading.
Hope this helps!

save writableimage to file in silverlight

How want to save the image of a canvas to a file.
var img = new WriteableBitmap(canvas1, null);
Image i = new Image();
i.Source = img;
var bitmap = new Bitmap(i);
I tried to use bitmap.Save( for saving the image but Bitmap is not supported by silverlight.
How would you save WriteableBitmap to a file?
The WriteableBitmap has a Pixels collection which can be used to access the rendered image. However you really need to get it stored in a known format (preferable PNG).
The imagetools codeplex project can do that for you.
See this blog for a simple example of using it for your purposes.

Resources