内存不足异常 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;
}
我正在开发一个 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;
}