Xamarin:Android - 大位图出现 OutOfMemory 异常 - 如何解决?
Xamarin:Android - OutOfMemory exception with large bitmap - how to solve?
我正在拍摄图像,解码由 TakePicture
方法生成的 byte array
,然后旋转 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);
请查看官方 Xamarin
文档中的 Load Large Bitmaps Efficiently,它解释了如何通过加载较小的子采样版本将大图像加载到内存中,而应用程序不会抛出 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);
}
希望对您有所帮助。
我正在拍摄图像,解码由 TakePicture
方法生成的 byte array
,然后旋转 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);
请查看官方 Xamarin
文档中的 Load Large Bitmaps Efficiently,它解释了如何通过加载较小的子采样版本将大图像加载到内存中,而应用程序不会抛出 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);
}
希望对您有所帮助。