Xamarin:Android - 带有大位图的OutOfMemory异常 - 如何解决?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Xamarin:Android - 带有大位图的OutOfMemory异常 - 如何解决?相关的知识,希望对你有一定的参考价值。

我正在拍摄一张图像,解码由byte array方法生成的TakePicture然后旋转bitmap 270度。问题是我似乎耗尽了内存,我不知道如何解决它。这是代码:

Bitmap image = BitmapFactory.DecodeByteArray (data, 0, data.Length);
data = null;
Bitmap rotatedBitmap = Bitmap.CreateBitmap (image, 0, 0, image.Width,
    image.Height, matrix, true);
答案

请查看官方Load Large Bitmaps Efficiently文档中的Xamarin,它解释了如何将大图像加载到内存中,而不会通过在内存中加载较小的子样本版本来投掷OutOfMemoryException

读取位图尺寸和类型

async Task<BitmapFactory.Options> GetBitmapOptionsOfImageAsync()
{
    BitmapFactory.Options options = new BitmapFactory.Options
    {
        InJustDecodeBounds = true
    };

    // The result will be null because InJustDecodeBounds == true.
    Bitmap result=  await BitmapFactory.DecodeResourceAsync(Resources, Resource.Drawable.someImage, options);

    int imageHeight = options.OutHeight;
    int imageWidth = options.OutWidth;

    _originalDimensions.Text = string.Format("Original Size= {0}x{1}", imageWidth, imageHeight);

    return options;
}

将缩小版本加载到内存中

public static int CalculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
{
    // Raw height and width of image
    float height = options.OutHeight;
    float width = options.OutWidth;
    double inSampleSize = 1D;

    if (height > reqHeight || width > reqWidth)
    {
        int halfHeight = (int)(height / 2);
        int halfWidth = (int)(width / 2);

        // Calculate a inSampleSize that is a power of 2 - the decoder will use a value that is a power of two anyway.
        while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth)
        {
            inSampleSize *= 2;
        }
    }

    return (int)inSampleSize;
}

将图像加载为异步

public async Task<Bitmap> LoadScaledDownBitmapForDisplayAsync(Resources res, BitmapFactory.Options options, int reqWidth, int reqHeight)
{
    // Calculate inSampleSize
    options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.InJustDecodeBounds = false;

    return await BitmapFactory.DecodeResourceAsync(res, Resource.Drawable.someImage, options);
}

并将其称为加载图像,例如在OnCreate

protected async override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.Main);
    _imageView = FindViewById<ImageView>(Resource.Id.resized_imageview);

    BitmapFactory.Options options = await GetBitmapOptionsOfImageAsync();
    Bitmap bitmapToDisplay = await LoadScaledDownBitmapForDisplayAsync (Resources, 
                             options, 
                             150,  //for 150 X 150 resolution
                             150);
    _imageView.SetImageBitmap(bitmapToDisplay);
}

希望能帮助到你。

以上是关于Xamarin:Android - 带有大位图的OutOfMemory异常 - 如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

将 Xamarin 表单页面捕获为位图而不附加到父级

Xamarin Android - 自定义通知托盘图标(状态栏)

Android:将大位图放在小位图后面,大位图应形成小位图

Android - 将带有位图的对象保存到文件

带有位图标记的 Android XML 可绘制圆角

带有原生 Android 工具栏的 Xamarin 表单