OutOfMemoryException throws on WriteableBitmap

I am developing one application for Windows that is useful for uploading images to a web server. I select all the images from my device in one list object . I convert all bitmaps to bytes [] one by one.

My code

public byte[] ConvertToBytes(BitmapImage bitmapImage) { byte[] data = null; WriteableBitmap wBitmap = null; using (MemoryStream stream = new MemoryStream()) { wBitmap = new WriteableBitmap(bitmapImage); wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100); stream.Seek(0, SeekOrigin.Begin); //data = stream.GetBuffer(); data = stream.ToArray(); DisposeImage(bitmapImage); return data; } } public void DisposeImage(BitmapImage image) { if (image != null) { try { using (MemoryStream ms = new MemoryStream(new byte[] { 0x0 })) { image.SetSource(ms); } } catch (Exception ex) { } } } 

Convert from Bitmap to Byte

  using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) { if (!store.DirectoryExists("ImagesZipFolder")) { //MediaImage mediaImage = new MediaImage(); //mediaImage.ImageFile = decodeImage(new byte[imgStream[0].Length]); //lstImages.Items.Add(mediaImage); store.CreateDirectory("ImagesZipFolder"); for (int i = 0; i < imgname.Count(); i++) { using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(@"ImagesZipFolder\" + imgname[i], FileMode.CreateNew,store)) //using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(@"ImagesZipFolder\text.txt" , System.IO.FileMode.OpenOrCreate, store)) { // byte[] bytes = new byte[imgStream[i].Length]; byte[] bytes = ConvertToBytes(ImgCollection[i]); stream.Write(bytes, 0, bytes.Length); } } } else { directory = true; } } 

I have 91 images in my emulator. When I convert all these bitmaps to byte [] , I get the following error in the line wBitmap = new WriteableBitmap(bitmapImage);

An exception of type "System.OutOfMemoryException" occurred in System.Windows.ni.dll, but was not processed in the user code

Error

What can I do to solve this error?

Web service

If we send a huge file to a web service, this gives an error, for example

An exception of type "System.OutOfMemoryException" occurred in System.ServiceModel.ni.dll, but was not processed in the user code

+4
source share
3 answers

What can I do to solve this error?

Change the way you work to use less memory.

For example, instead of converting each image and then uploading it, converting the image, uploading it, converting the next one, etc.

If you really want to process all the snapshots at once, you can store byte arrays in isolated storage rather than store them in memory and read them if necessary.

Basically, rethink your process and use storage to use less memory at a given time.

This or ask Microsoft to remove the memory limit on Windows Phone, but it can be a little more complicated.

+2
source

The problem is how the GC and bitmaps work together as described in this bug report: https://connect.microsoft.com/VisualStudio/feedback/details/679802/catastrophic-failure-exception-thrown-after-loading -too-many-bitmapimage-objects-from-a-stream # details

From the report:

When Silverlight loads an image, the structure maintains the link and caches the decoded image until flow control is returned to the stream manager user interface. When you upload images in such a closed loop, even if your application does not save the link, GC cannot release the image until we release our link when the flow control is back.

After processing 20 or so images, you can stop and queue the next install using Dispatcher.BeginInvoke just to break up the work that is processed in one batch. This will allow us to release images that are not saved by the application.

I understand that with the current decoding mode, it is not obvious that Silverlight stores these links, but changing the decoder design may affect other areas, so for now I recommend processing images like this in batches.

Now, if you are actually trying to load 500 images and save them, you will still probably end up with a lack of memory depending on the size of the image. If you are dealing with a multi-page document, you may want to instead load pages on demand in the background and release them when you look through several pages of the buffer so that in no case do you exceed reasonable limits of texture memory.

Fix:

 private List<BitmapImage> Images = .....; private List<BitmapImage>.Enumerator iterator; private List<byte[]> bytesData = new List<byte[]>(); public void ProcessImages() { if(iterator == null) iterator = Images.GetEnumerator(); if(iterator.MoveNext()) { bytesData.Add(ConvertToBytes(iterator.Current)); //load next images Dispatcher.BeginInvoke(() => ProcessImages()); }else{ //all images done } } public static byte[] ConvertToBytes(BitmapImage bitmapImage) { using (MemoryStream stream = new MemoryStream()) { var wBitmap = new WriteableBitmap(bitmapImage); wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100); stream.Seek(0, SeekOrigin.Begin); return stream.ToArray(); } } 
+1
source

I found a new way to convert Bitmap Image to byte [] array. No need to write an image in memory. A hare is a code

  public byte[] GetBytes(BitmapImage bi) { WriteableBitmap wbm = new WriteableBitmap(bi); return ToByteArray(wbm); } public byte[] ToByteArray(WriteableBitmap bmp) { // Init buffer int w = bmp.PixelWidth; int h = bmp.PixelHeight; int[] p = bmp.Pixels; int len = p.Length; byte[] result = new byte[4 * w * h]; // Copy pixels to buffer for (int i = 0, j = 0; i < len; i++, j += 4) { int color = p[i]; result[j + 0] = (byte)(color >> 24); // A result[j + 1] = (byte)(color >> 16); // R result[j + 2] = (byte)(color >> 8); // G result[j + 3] = (byte)(color); // B } return result; } 
0
source

Source: https://habr.com/ru/post/1494280/


All Articles