Windows Phone 8的Out of Memory异常BitMapImage

时间:2014-12-01 05:49:24

标签: c# .net windows-phone-8 windows-phone-8.1

单击图片两到三次后,我在appCapImg.SetSource中出现内存不足异常。我尝试用一​​些内存工具进行分析,但我找不到问题。我做错了吗

   byte[] data = null;
 public PhotoCamera cam;
 fnInitializeCamera();

      private void fnInitializeCamera()
    {
        gobject.txtMessage.Text = "Tap the screen to capture a photo.";
        if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true)
        {
            cam = new PhotoCamera(CameraType.Primary);
            cam.CaptureImageAvailable += new    EventHandler<Microsoft.Devices.ContentReadyEventArgs>(cam_CaptureImageAvailable);
            gobject.viewfinderBrush.SetSource(cam);
            if (gobject.Orientation == PageOrientation.PortraitUp)
            {
                gobject.viewfinderTransform.Rotation = 90.0;
            }
        }
        else
        {
            gobject.txtMessage.Text = "A Camera is not available on this device.";
        }
    }

    public void viewfinder_Tapped(object sender, GestureEventArgs e)
    {
        gobject.txtMessage.Text = "Saving Image..";
        if (cam != null)
        {
            try
            {
                cam.CaptureImage();
            }
            catch (Exception ex)
            {
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    gobject.txtMessage.Text = ex.Message;
                });
            }
        }
    }

private void RotateStream(Stream stream, int angle)
    {


        stream.Position = 0;
        if (angle % 90 != 0 || angle < 0) throw new ArgumentException();
        if (angle % 360 == 0) data= ((MemoryStream)stream).ToArray(); 

        BitmapImage bitmap = new BitmapImage();
        bitmap.DecodePixelWidth = 480;
        bitmap.SetSource(stream);
        stream.Dispose();
        WriteableBitmap wbSource = new WriteableBitmap(bitmap);
        bitmap.UriSource = null;

        WriteableBitmap wbTarget = null;
        if (angle % 180 == 0)
        {
            wbTarget = new WriteableBitmap(wbSource.PixelWidth, wbSource.PixelHeight);
        }
        else
        {
            wbTarget = new WriteableBitmap(wbSource.PixelHeight, wbSource.PixelWidth);
        }

        int width = wbSource.PixelWidth;
        int height = wbSource.PixelHeight;
        int targetWidth = wbTarget.PixelWidth;
        int[] sourcePixels = wbSource.Pixels;
        int[] targetPixels = wbTarget.Pixels;

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                switch (angle % 360)
                {
                    case 90:
                        targetPixels[(height - y - 1) + x * targetWidth] = sourcePixels[x + y * width];
                        break;
                    case 180:
                        targetPixels[(width - x - 1) + (height - y - 1) * width] = sourcePixels[x + y * width];
                        break;
                    case 270:
                        targetPixels[y + (width - x - 1) * targetWidth] = sourcePixels[x + y * width];
                        break;
                }
            }
        }

        using (MemoryStream targetStream = new MemoryStream())
        {
            wbTarget.SaveJpeg(targetStream, width, height, 0, 100);

            data = targetStream.ToArray();

        }
    }

    void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
    {
        cam.Dispose();
        Deployment.Current.Dispatcher.BeginInvoke(delegate()
        {
            gobject.disableCameraPlugin();
            gobject.enableWebBrowser();
            BitmapImage appCapImg = new BitmapImage();


            if (gobject.Orientation == PageOrientation.PortraitUp)
            {
                RotateStream(e.ImageStream, 90);
              // Stream stream = new MemoryStream(data1);
               using (MemoryStream streamT = new MemoryStream(data))
               {

                   appCapImg.SetSource(streamT);
               }
               data = null;

            }
            else
            {
                RotateStream(e.ImageStream, 180);
                e.ImageStream.Dispose();
                using (MemoryStream streamT = new MemoryStream(data))
                {

                    appCapImg.SetSource(streamT);
                }
                data = null;

            }

            using (MemoryStream stream = new MemoryStream())
                    {
                        WriteableBitmap wBitmap = new WriteableBitmap(appCapImg);
                        appCapImg.UriSource = null;
                        wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 40);
                        stream.Seek(0, SeekOrigin.Begin);
                        data = stream.ToArray();
                    }
                    string base64 = Convert.ToBase64String(data);
                    string[] invokeparam1 = { htmlid, base64 };
                    invokeScript("showimage", invokeparam1);
 }

1 个答案:

答案 0 :(得分:0)

正如我经常说的那样,MemoryStream应该谨慎处理。您始终可以认为在使用MemoryStream对象后调用dispose是必须的。在以下代码中,您已经优雅地处理了这个问题,

using (MemoryStream stream = new MemoryStream()) { .... }

您永远不应该直接从方法返回任何Streams。它没有任何问题,除了它违反了你之前申请手动调用所有Stream对象上的Dispose()的原则。因此,您可以尝试从您的方法返回byte []而不是Stream。

private Stream RotateStream(Stream stream, int angle)

并始终在using {...}块中包含所有流对象。同样,您的代码看起来不完整。就像变量“e”代表什么一样。