Image loading time in windows phone apps - c#

i m creating a app in which I need to change the source of the image on button click.eg if the images are:
sample1.png, sample2.png, sample3.png ...
I have written this code on button click:
int count=1;
imagename.Source=new BitmapImage(new uri("/sample"+count+".png",uriKind.Relative));
but the problem is when I run the app on a device it takes some time to load the image source everytime the button is clicked whereas on the emulator it changes properly.is there any way to reduce the loading time on device?

is there any way to reduce the loading time on device?
As far as I know: no. If performance is unsatisfactory, you may want to try with some caching. Basically, instead of creating a new BitmapImage each time, re-use the old ones.
First, pre-load the bitmaps. Don't forget to set the CreateOptions property, otherwise the picture won't be loaded until you assign it to an actual Image control:
var bitmaps = new List<BitmapImage>(count);
for (int i = 0; i < count; i++)
{
var bitmap = new BitmapImage(new uri("/sample" + i + ".png",uriKind.Relative));
bitmap.CreateOptions = BitmapCreateOptions.None;
bitmaps.Add(bitmap);
}
Then, re-use them as needed:
imagename.Source = bitmaps[1];
Please be aware that it will increase the memory usage of your app, so don't do that with large pictures. Performance is often a compromise between CPU time and memory usage.

Like KooKiz said you can prefetch the image but to force the load of the images, I believe you will need to use SetSourceAsync, here is an example:
StorageFile file= await StorageFile.GetFileFromApplicationUriAsync(new Uri("appx-data:////sample" + i + ".png"));
using (var stream = await file.OpenReadAsync())
{
bitmap.SetSourceAsync(stream);
}
Also what could be possible to do is for you to preload a thumbnail version of the image first (by using file.GetThumbnailAsync for example) and then the full image latter.
Finally if the images you are loading are actually bigger than the resolution of the surface you are loading it on, another parameter you can set on the Bitmap object is DecodePixelHeight and DecodePixelWidth.

int count=1;
BitmapImage bmp=new BitmapImage();
StorageFile sFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(#"Assets\Images\img" + count + ".png");
var fileStream = await sFile.OpenReadAsync();
await bmp.SetSourceAsync(fileStream);

Related

C# How to create in-memory video chunks

I need to record screen and on event like button click it should save last 60 seconds of recording.
I know how to capture screenshots but I have problems with converting the images to the video. I want to save the final video file and everything else should be in memory operations.
Currently I save captures as JPEG to memory stream and when the event is fired then I convert the images to the video files. But there is tripple conversion: Bitmap[] -> JPEG[] -> Bitmap[] -> Video. That seems ineffective.
When I googled I found only how to save video file to file system. For example Accord library have VideoFileWritter (example for version 3.8.2 alpha)
Bitmap bitmap; //bitmap object with screenshot
List<byte[]> data = new List<byte[]>();
// fill data with JPEG images (called periodically)
using (var ms = new MemoryStream())
{
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
data.Add(ms.GetBuffer());
}
// create video file (called on demand)
using (VideoFileWriter videoWriter = new VideoFileWriter())
{
videoWriter.BitRate = videoBitRate;
videoWriter.FrameRate = Settings.CurrentFramesPerSeconds;
videoWriter.Width = 1920;
videoWriter.Height = 1080;
videoWriter.VideoCodec = VideoCodec.H264;
videoWriter.VideoOptions["crf"] = "18"; // visually lossless
videoWriter.VideoOptions["preset"] = "veryfast";
videoWriter.VideoOptions["tune"] = "zerolatency";
videoWriter.VideoOptions["x264opts"] = "no-mbtree:sliced-threads:sync-lookahead=0";
videoWriter.Open(Path.Combine(dirName, "output.avi"));
foreach (var frame in data)
{
using (var bmpStream = new MemoryStream(frame))
using (var img = Image.FromStream(bmpStream))
using (var bmp = new Bitmap(img))
videoWriter.WriteVideoFrame(bmp);
}
}
How to create video chunks in memory? I guess it should be CPU and memory more efficient than my current solution.
Or is there more efficient way to record last few seconds of screen without file system usage?
I don't want to use file system because only ssd is installed in computer.

pictureBox updating slowly in C# GUI?

I am taking images with a machine vision camera and storing them into a folder. I want to show the saved image in a pictureBox before the next image is stored. My code is successfully showing the image in the pictureBox, however, there is a delay so i.e by the time image 10 is saved to the folder the GUI is only showing image 3. I am not sure how to increase the performance to allow the GUI to update in real time as I am taking images.
I think my problem may be due to using the png image to create the MemoryStream instead of the byte[] buffer (raw sensor data). I have attempted using the byte[] but I was not able to successfully populate the pictureBox.
This is my code:
// Grab a number of images.
for (int i = 0; i < num_images; ++i)
{
// Wait for an image and then retrieve it. A timeout of 5000 ms is used.
IGrabResult grabResult = camera.StreamGrabber.RetrieveResult(5000,
TimeoutHandling.ThrowException);
using (grabResult)
{
// Image grabbed successfully?
if (grabResult.GrabSucceeded)
{
buffer = grabResult.PixelData as byte[];
//ImageWindow.DisplayImage(0, grabResult);
file_extension = "Position_" + i + ".png";
image_filename = String.Concat(image_filepath, file_extension);
ImagePersistence.Save(ImageFileFormat.Png, image_filename, grabResult);
//image_algorithms();
Image image = Image.FromFile(image_filename);
var ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
var bytes = ms.ToArray();
var imageMemoryStream = new MemoryStream(bytes);
Image imgFromStream = Image.FromStream(imageMemoryStream);
pictureBox1.Image = imgFromStream;
pictureBox1.Refresh();
}
else
{
Console.WriteLine("Error: {0} {1}", grabResult.ErrorCode,
grabResult.ErrorDescription);
}
}
}

C# MemoryStream slowing programme performance

I'm working on a project using WPF to display the Kinect ColorImageFrame and a skeleton representation. I also have to record those two videos.
I'm able to display and record (using EmguCV) those two images, but I have some performance issues. It seems that this part of my code is the reason of my loss of performance.
private void DrawSkeleton(Skeleton[] skeletons)
{
using (System.Drawing.Bitmap skelBitmap = new System.Drawing.Bitmap(640, 480))
{
foreach (Skeleton S in skeletons)
{
if (S.TrackingState == SkeletonTrackingState.Tracked)
{
DrawBonesAndJoints(S,skelBitmap);
}
else if (S.TrackingState == SkeletonTrackingState.PositionOnly)
{
}
}
_videoArraySkel.Add(ToOpenCVImage<Bgr, Byte>(skelBitmap));
BitmapSource source = ToWpfBitmap(skelBitmap);
this.skeletonStream.Source = source;
}
}
and more precisely from the ToWpfBitmap which allows me to display it in my Window:
public static BitmapSource ToWpfBitmap(System.Drawing.Bitmap bitmap)
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
stream.Position = 0;
BitmapImage result = new BitmapImage();
result.BeginInit();
// According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
// Force the bitmap to load right now so we can dispose the stream.
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
The loss of performance is characterized by:
- The videos displayed on the Window are not fluent anymore
- The video recording seems to miss some frames which leads to a video going faster/lower than the normal.
Can you help me by telling me where this problem may come from?
Try to use RecyclableMemoryStream instead of MemoryStream. It was designed for solving some issue with memory.
Check out this article for details - Announcing Microsoft.IO.RecycableMemoryStream
Have you tried doing the memory write i/o in a separate thread, while maintaining the data in a buffer like a queue?

How to properly dispose of resources in wpf

Hi I have an application in which I have to save images from three different IP Cameras whenever a button is pressed.
I am using a class that has all the members that I need to save the images from the IP camera namely the BitmapImage and the DateTime of when the photo was saved.
I have the following problem. I need to save a certain amount of photos of each camera every couple hundred milliseconds. And I am currently testing it by saving 50 photos of each camera every 200ms to a ConcurrentQueue and then the items gets saved from the ConcurrentQueue to file. After I have taken about 110 photos altogether of all three cameras then it just saves blank images.
I think my problem is that the program memory is too full, so I need to clear an item from the memory when ever I save the item with the TryDequeue() method of the ConcurrentQueue.
Can anyone please advise me or give me maybe some links that can help me to save this problem so that I can save as many photos as I want to of each camera and that it will not run out of memory after a certain amount photos?
A button is pressed and then it goes into a for loop where it calls the following method.
private void EnqueuePhotos1()
{
IPCamera1 ipCam1Enqueue = new IPCamera1();
BitmapImage cam1Image = new BitmapImage();
cam1Image.BeginInit();
cam1Image.CacheOption = BitmapCacheOption.OnLoad;
cam1Image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
cam1Image.UriSource = null;
cam1Image.UriSource = new Uri("http://" + ipCam1IP + "/image?res=full&x0=0&y0=0&x1=1600&y1=1200&quality=21&doublescan=0", UriKind.Absolute);
while (cam1Image.IsDownloading) { ; }
cam1Image.EndInit();
ipCam1Enqueue.IPCamImage = cam1Image;
ipCam1Enqueue.TimeTook = DateTime.Now;
ipCam1ConQ.Enqueue(ipCam1Enqueue);
}
for a certain amount of times depending on how many photos the user wants to take.
Just before the for loop I start my timer to check every 100ms if there is something on the ConcurrentQueue and then if something is found it calls the following function.
private void GetPhotos1()
{
IPCamera1 ipCam1Dequeue = new IPCamera1();
while (ipCam1ConQ.TryDequeue(out ipCam1Dequeue))
{
cam1Photos++;
cam1ImgLoc = cam1Location + "\\Image " + cam1Photos + ".jpg";
FileStream cam1Stream = new FileStream(cam1ImgLoc, FileMode.Create);
JpegBitmapEncoder cam1Encoder = new JpegBitmapEncoder();
cam1Encoder.Frames.Add(BitmapFrame.Create(ipCam1Dequeue.IPCamImage));
cam1Encoder.Save(cam1Stream);
cam1Stream.Dispose();
}
}
using (FileStream cam1Stream = new FileStream(cam1ImgLoc, FileMode.Create))
{
// do stuff...
}
Resources defined in a way like this are automagically disposed after the statements in the using statement are executed.

WPF Images not rendering from in-memory sources

I have a data class in my application which maintains a collection of byte arrays representing JPEG images. It's defined as:
private ArrayList FrameList = new ArrayList();
I'm having some troubles with my Image object rendering a blank page (and taking its sweet time to do it as well). When I insert a blank image with a 2K in-memory byte array (byte x[] = { lots of hex values };):
FrameList.Insert(currFrame, x);
and then import a JPEG file over it later on with:
byte[] bytes = File.ReadAllBytes(fspec);
FrameList[currFrame] = bytes;
the array is read correctly into memory and stored in the ArrayList (confirmed with the debugger).
However,I then have a function to get the image:
public BitmapImage getCurrPicture()
{
MemoryStream strm;
BitmapImage bmp = new BitmapImage();
strm = new MemoryStream((byte[])FrameList[currFrame-1]);
bmp.CacheOption = BitmapCacheOption.None;
bmp.BeginInit();
bmp.StreamSource = strm;
bmp.EndInit();
strm.Close();
return bmp;
}
which is called:
imgPicB.Source = data.getCurrPicture();
and it doesn't always render.
imgPicB is defined in my XAML as:
<Image x:Name="imgPicB"
Width="400"
Height="300"
Stretch="Fill"
VerticalAlignment="Top" />
Funny thing is, if I use the exact same JPEG setting the source with setting the source to the file URI directly, it renders fine.
Is there some problem with using in-memory JPEG images in WPF? Is there some extra smarts performed when loading from a file (say auto-detection of the image type)?
Try this:
public BitmapSource GetCurrPicture()
{
var bitmapImage = new BitmapImage();
using (Stream stream = new MemoryStream((byte[])FrameList[currFrame-1]))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
This works by having WPF decode the image immediately with OnLoad, and then release the reference to the stream when it is done. This means the stream can be garbage collected when it leaves the function. Otherwise, BitmapImage could hold onto the stream until it is rendered.
In the code posted in the question, the render would fail because:
the decode is delayed; and
the stream has been closed at the point where the decode tries to happen.
Link
DwayneNeed 20 Jun 2008 5:11 PM Comments
Caching BitmapImage will store the decoded bitmap in system memory. You can control when this happens by setting the CacheOption property. BitmapImage also maintains a cache of previous BitmapImage instances (via weak references) so that loading the same Uri multiple times will share the same instance. To avoid this cache, you can include the BitmapCreateOptions.IgnoreImageCache flag in the CreateOptions property.

Categories

Resources