内存不足异常 Windows Phone 8.1

Out of Memory Exception Windows Phone 8.1

我正在开发一个 windows phone 8.1 应用程序,它可以拍摄照片、存储照片并将其放入可写位图中,以便我可以旋转它以准确显示结果。碰巧我需要使用两个可写位图来做到这一点。 我还将图像转换为字节,以便在必要时可以通过服务发送它。

以下步骤会产生异常:

我拍照,说没关系,它给我显示照片。 接下来我尝试拍另一张照片,因为我对之前的结果不满意,并且在

上出现内存不足异常

newWriteableBitmap = writeableBitmap.Rotate(90);

我写入相同的变量,相同的视图模型,相同的一切。好像某处似乎有某种内存泄漏?我真的很想避免 GC.collect 和相关的。我接受任何形式的改进和建议,我相信代码可以重构得更好。

谢谢,

private async Task TakePhoto()
        {
            _mediaCapture.VideoDeviceController.FlashControl.Auto = false;
            _mediaCapture.VideoDeviceController.FlashControl.Enabled = ((CameraViewModel) this.DataContext).FlashEnable;
            if (_mediaCapture.VideoDeviceController.FocusControl.Supported)
            {
                await _mediaCapture.VideoDeviceController.FocusControl.FocusAsync();
            }

            if (_mediaCapture.VideoDeviceController.TorchControl.Supported)
            {
                _mediaCapture.VideoDeviceController.TorchControl.Enabled = true;
            }
            Guid guid = Guid.NewGuid();
            ImageEncodingProperties imageEncodingProperties = ImageEncodingProperties.CreateJpeg();
            StorageFile cardStorageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("cardStorageFile" + guid.ToString() + ".jpg", CreationCollisionOption.ReplaceExisting);
            await _mediaCapture.CapturePhotoToStorageFileAsync(imageEncodingProperties, cardStorageFile);


            ((CameraViewModel)this.DataContext).CardBitmapImage = new BitmapImage(new Uri(cardStorageFile.Path));
            await ((CameraViewModel)this.DataContext).CardBitmapImage.SetSourceAsync(await cardStorageFile.OpenAsync(FileAccessMode.Read));

            WriteableBitmap writeableBitmap = new WriteableBitmap(((CameraViewModel)this.DataContext).CardBitmapImage.PixelWidth, ((CameraViewModel)this.DataContext).CardBitmapImage.PixelHeight);
            using (IRandomAccessStream stream = await cardStorageFile.OpenAsync(FileAccessMode.Read))
            {
                await writeableBitmap.SetSourceAsync(stream);
            }
            WriteableBitmap newWriteableBitmap = new WriteableBitmap(((CameraViewModel)this.DataContext).CardBitmapImage.PixelHeight, ((CameraViewModel)this.DataContext).CardBitmapImage.PixelWidth);
            newWriteableBitmap = writeableBitmap.Rotate(90);

            PhotoPreviewImage.Source = newWriteableBitmap;

            await ImageTobyte(cardStorageFile, value => ((CameraViewModel)this.DataContext).CardByte = value);
            ((CameraViewModel)this.DataContext).CaptureEnable = false;
            ((CameraViewModel)this.DataContext).IsBusy = false;
        }



        public async Task<byte[]> ImageTobyte(StorageFile myImageFile, Action<byte[]> setResultAction)
        {
            using (Stream ms = await myImageFile.OpenStreamForReadAsync())
            {
                byte[] imageBytes = new byte[(int) ms.Length];
                ms.Read(imageBytes, 0, (int) ms.Length);
                setResultAction(imageBytes);
                return imageBytes;
            }
        }

我通过如下所示进行重大重构找到了自己的解决方案。我相信还有一些可以改进的地方。

private async Task TakePhoto()
        {
            _mediaCapture.VideoDeviceController.FlashControl.Auto = false;
            _mediaCapture.VideoDeviceController.FlashControl.Enabled = ((CameraViewModel) this.DataContext).FlashEnable;
            if (_mediaCapture.VideoDeviceController.FocusControl.Supported)
            {
                await _mediaCapture.VideoDeviceController.FocusControl.FocusAsync();
            }

            if (_mediaCapture.VideoDeviceController.TorchControl.Supported)
            {
                _mediaCapture.VideoDeviceController.TorchControl.Enabled = true;
            }

            ImageEncodingProperties imageEncodingProperties = ImageEncodingProperties.CreateJpeg();
            Guid guid = Guid.NewGuid();
            StorageFile cardStorageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("cardStorageFile" + guid.ToString() + ".jpg", CreationCollisionOption.ReplaceExisting);

            using (var imageStream = new InMemoryRandomAccessStream())
            {
                await _mediaCapture.CapturePhotoToStreamAsync(imageEncodingProperties, imageStream);

                BitmapDecoder dec = await BitmapDecoder.CreateAsync(imageStream);
                BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(imageStream, dec);

                enc.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;

                await enc.FlushAsync();


                using (var fileStream = await cardStorageFile.OpenStreamForWriteAsync())
                {
                    try
                    {
                        await RandomAccessStream.CopyAsync(imageStream, fileStream.AsOutputStream());
                    }
                    catch(Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
            }

            using (var randomAccessStream = await cardStorageFile.OpenAsync(FileAccessMode.ReadWrite))
            {
                if (((CameraViewModel) this.DataContext).CardBitmapImage == null)
                {
                    VideoEncodingProperties photoSizeEncodingProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.Photo) as VideoEncodingProperties;

                    if (photoSizeEncodingProperties != null)
                    {
                        ((CameraViewModel) this.DataContext).CardBitmapImage = new WriteableBitmap((int) photoSizeEncodingProperties.Width, (int) photoSizeEncodingProperties.Height);
                    }
                }
                await ((CameraViewModel)this.DataContext).CardBitmapImage.SetSourceAsync(randomAccessStream);
            }

            ((CameraViewModel) this.DataContext).StorageFileImage = cardStorageFile;

            ((CameraViewModel)this.DataContext).CaptureEnable = false;
            ((CameraViewModel)this.DataContext).IsBusy = false;
        }