在Android中使用图像选择的OutOfMemoryError.如何在将图像解码为位图之前调整图像大小?

kra*_*r65 0 java android image out-of-memory image-resizing

我正在我的Android应用程序中构建一个imagepicker,我在这个页面上使用了示例代码.这基本上给了我一个按钮,可以从SD卡中获取文件,或者通过拍照获得文件.选择图像后,它会使用简单的ImageView显示图像.总的来说,这非常有效; 我可以选择图像,然后再次单击选择图像按钮并选择另一个图像.到目前为止这么好..有小文件.

当我使用"更大的文件"时,问题就开始了; 我只是用内置手机摄像头拍摄的照片.我可以选择一个,这很有效.当我再次点击选择图像按钮并选择另一个图像时,我在此行上得到一个OutOfMemoryError(链接到页面的第75行):

bitmap = BitmapFactory.decodeFile(path);
Run Code Online (Sandbox Code Playgroud)

我的测试设备非常现代(Galaxy S4 Mini),所以这应该不是问题.由于我需要将图像作为base64字符串发送到我需要调整大小的API,我可以使用以下内容调整图像大小:

Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
Run Code Online (Sandbox Code Playgroud)

但不幸的是,为此我首先需要解码文件,这实际上首先导致了问题.

所以我的问题是; 有没有办法在将图像解码为位图之前调整图像大小?欢迎所有提示!

Pre*_*rem 6

在加载大型位图文件时,BitmapFactory类提供了几种解码方法(decodeByteArray(),decodeFile(),decodeResource()等).

步骤1

解码时将inJustDecodeBounds属性设置为true可避免内存分配,为位图对象返回null但设置outWidth,outHeight和outMimeType.此技术允许您在构造(和内存分配)位图之前读取图像数据的尺寸和类型.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Run Code Online (Sandbox Code Playgroud)

要避免java.lang.OutOfMemory异常,请在解码之前检查位图的尺寸.

第2步

要告诉解码器对图像进行子采样,将较小的版本加载到内存中,请在BitmapFactory.Options对象中将inSampleSize设置为true.

例如,使用inSampleSize为4解码的分辨率为2048x1536的图像会产生大约512x384的位图.将其加载到内存中对于完整图像使用0.75MB而不是12MB.

这是一种根据目标宽度和高度计算样本大小值的方法,该值为2的幂:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

    final int halfHeight = height / 2;
    final int halfWidth = width / 2;

    // Calculate the largest inSampleSize value that is a power of 2 and keeps both
    // height and width larger than the requested height and width.
    while ((halfHeight / inSampleSize) > reqHeight
            && (halfWidth / inSampleSize) > reqWidth) {
        inSampleSize *= 2;
    }
}

return inSampleSize;
}
Run Code Online (Sandbox Code Playgroud)

请阅读此链接了解详情.http://developer.android.com/training/displaying-bitmaps/load-bitmap.html