相机通过意图返回的位图大小?

Ixx*_*Ixx 13 memory camera android bitmap

如何从相机获取具有特定(内存友好)大小的位图?

我正在开始一个相机意图:

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
cameraIntent.putExtra("return-data", true);

photoUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "mytmpimg.jpg"));
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoUri);        

startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA);
Run Code Online (Sandbox Code Playgroud)

我在这里处理结果:

//  Bitmap photo = (Bitmap) intent.getExtras().get("data");

Bitmap photo = getBitmap(photoUri);
Run Code Online (Sandbox Code Playgroud)

现在,如果我使用注释行 - 直接获取位图,我总是得到一个160 x 120位图,而且这个位图太小了.如果我使用我发现的一些标准内容(方法getBitmap)从URI加载它,它会加载一个2560 x 1920位图(!)并消耗近20 MB的内存.

如何加载让我们说480 x 800(相机预览显示的尺寸相同)?

无需将2560 x 1920加载到内存中并缩小.

Ixx*_*Ixx 2

这是我根据作物库中名为 getBitmap() 的方法想到的,该方法已从旧 Android 版本中删除。我做了一些修改:

private Bitmap getBitmap(Uri uri, int width, int height) {
    InputStream in = null;
    try {
        int IMAGE_MAX_SIZE = Math.max(width, height);
        in = getContentResolver().openInputStream(uri);

        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        BitmapFactory.decodeStream(in, null, o);
        in.close();

        int scale = 1;
        if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
            scale = (int)Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        //adjust sample size such that the image is bigger than the result
        scale -= 1;

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        in = getContentResolver().openInputStream(uri);
        Bitmap b = BitmapFactory.decodeStream(in, null, o2);
        in.close();

        //scale bitmap to desired size
        Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, width, height, false);

        //free memory
        b.recycle();

        return scaledBitmap;

    } catch (FileNotFoundException e) {
    } catch (IOException e) {
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

其作用是使用 BitmapFactory.Options() + 一些样本大小加载位图 - 这样原始图像不会加载到内存中。问题是样本大小只是逐步起作用。我使用复制的一些数学公式得到图像的“最小”样本大小,然后减去 1 以获得产生最小值的样本大小。位图比我需要的尺寸大。

然后为了获得与所请求的大小完全相同的位图,请使用 进行正常缩放Bitmap.createScaledBitmap(b, width, height, false);。并立即回收更大的位图。这很重要,因为,例如,在我的例子中,为了获得 480 x 800 位图,较大的位图是 1280 x 960,占用 4.6mb 内存。

一种对内存更友好的方法是不进行调整scale,因此较小的位图将被放大以匹配所需的大小。但这会降低图像质量。