2

I would like to save a photo, taken within my App(using CameraCaptureTask), to the isolated storage. The current Problem is the consumption of RAM, which always leads to an OutOfMemoryException. This also happens when I am loading the picture into an Image-Control.

My App should finally be able to take 10 pictures, save them to isolated storage, show them in an Image Control and if necessary delete the picture for good.

Lowering the resolution of the pictures logically fixed the exception, but that's not the way I wanted to go.

Maybe you can give me a hint.

Here is my code:

private CameraCaptureTask ccTask = new CameraCaptureTask();
WriteableBitmap[] imgList = new WriteableBitmap[10];
Random rnd = new Random();

private void addPicture_button_Click(object sender, EventArgs e)
{
    ccTask.Show();
    ccTask.Completed += ccTask_Completed;
}

void ccTask_Completed(object sender, PhotoResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            WriteableBitmap writeableBitmap = new WriteableBitmap(1600,1200);
            writeableBitmap.LoadJpeg(e.ChosenPhoto);

            string imageFolder = "Unfaelle";
            string datetime = DateTime.Now.ToString().Replace("/","");
            datetime = datetime.Replace(":","");
            string imageFileName = "Foto_"+datetime+".jpg";
            using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
            {

                if (!isoFile.DirectoryExists(imageFolder))
                {
                    isoFile.CreateDirectory(imageFolder);
                }

                string filePath = System.IO.Path.Combine(imageFolder, imageFileName);
                using (var stream = isoFile.CreateFile(filePath))
                {
                    writeableBitmap.SaveJpeg(stream, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight, 0, 100);
                }
            }

            //now read the image back from storage to show it worked...
            BitmapImage imageFromStorage = new BitmapImage();

            using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                string filePath = System.IO.Path.Combine(imageFolder, imageFileName);
                using (var imageStream = isoFile.OpenFile(
                    filePath, FileMode.Open, FileAccess.Read))
                {
                    imageFromStorage.SetSource(imageStream);
                }
            }

            Rectangle b = new Rectangle()
            {
                Width = 100,
                Height = 100,
            };

            Thickness margin = b.Margin;
            margin.Left = 10;
            margin.Top = 10;
            b.Margin = margin;

            ImageBrush imgBrush = new ImageBrush();
            imgBrush.ImageSource = imageFromStorage;
            b.Fill = imgBrush;
            b.Tag = System.IO.Path.Combine(imageFolder, imageFileName);
            b.Tap += OnTapped;

            pictures_wrapPanel.Children.Add(b);
        }
    }

private void OnTapped(object sender, System.Windows.Input.GestureEventArgs e)
        {

            Rectangle r = sender as Rectangle;
            BitmapImage imageFromStorage = new BitmapImage();

            using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                string filePath = r.Tag.ToString();
                using (var imageStream = isoFile.OpenFile(
                    filePath, FileMode.Open, FileAccess.Read))
                {
                    imageFromStorage.SetSource(imageStream);
                }
            }
            img.Source = imageFromStorage;
        }

Thanks a lot, if there is anything unclear, feel free to ask. Maybe there is a much easier way to save a photo, I am just beginning with app development Greetings Daniel

Btw: 1600x1200 are 2MP, I lowered the resolution to avoid the exception, unfortunately it was just delayed

Daniel Abou Chleih
  • 2,440
  • 2
  • 19
  • 31

1 Answers1

3

10 pictures with a resolution of 1600 * 1200 use about 80MB of ram. The memory limit is 90 MB on Windows Phone 7 and 150 MB on Windows Phone 8, there's no way what you're trying to do could work.

My App should finally be able to take 10 pictures, save them to isolated storage, show them in an Image Control and if necessary delete the picture for good.

This approach is correct, however you are loading the full-sized picture to display in the thumbnails, which is a total waste of RAM. When you're saving the picture to the isolated storage, save a copy with a lower resolution and display that copy in the thumbnail. Then, when the user tap on a thumbnail, load the full-res picture from the isolated storage to display it.

Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94
  • I followed your advice and it seems to work. Now that I am monitoring the RAM-Usage(see http://developer.nokia.com/Community/Wiki/Reporting_memory_usage_on_Windows_Phone) I realize it is often almost hitting the memory limit, but then the current usage is dropping from one operation to the next. Is this a normal behavior? – Daniel Abou Chleih Jul 18 '13 at 19:28
  • 1
    @DanielAbouChleih That's how memory is managed on Windows Phone and on every .NET application. There's a process running in the background, called the garbage collector. Under some conditions (like when the memory is running low), a collection is triggered and it will free all the memory you're not using anymore. You can trigger a collection manually by calling `GC.Collect()` but it's usually not necessary. – Kevin Gosse Jul 18 '13 at 19:42
  • How can i download a file of size > 150 MB from a remote location directly to isolated storage without any out of memory exceptions? – Sebastian Feb 10 '14 at 07:00
  • See more details here http://stackoverflow.com/questions/21671157/save-to-isolated-storage-directly-in-wp8 – Sebastian Feb 10 '14 at 08:13