解码采样位图如果太大则返回null

时间:2015-08-27 06:57:38

标签: java android image bitmap decode

我正在尝试解码在Android设备上拍摄的图像而不会耗尽设备上的内存,我终于遇到了this指南并跟着它导致了这3种方法:

public static FileDescriptor getDescriptorFromFile(File file, Context context) throws FileNotFoundException {
    Uri photoUri = Uri.fromFile(file);

    ContentResolver resolver = context.getContentResolver();
    ParcelFileDescriptor pfd = resolver.openFileDescriptor(photoUri, "r");
    FileDescriptor fd = pfd.getFileDescriptor();

    return fd;
}

public static Bitmap decodeSampledBitmap(FileDescriptor descriptor, int reqWidth, int reqHeight) {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFileDescriptor(descriptor, null, options);

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

    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFileDescriptor(descriptor, null, options);
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

    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;

        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

这些方法的用法如下:

ImageView imageView = (ImageView) findViewById(R.id.photo_taken);
int width = imageView.getMeasuredWidth();
int height = imageView.getMeasuredHeight();

final FileDescriptor fd = CameraUtils.getDescriptorFromFile(filePath, this);
Bitmap bitmap = CameraUtils.decodeSampledBitmap(fd, 250, 250);
imageView.setImageBitmap(bitmap);

理想情况下,我希望将250个值设置为视图的宽度和高度,但是当我制作它们时,任何更大的decodeSampleBitmap()都会返回null并且我不能为我的生活找出原因吗?

非常感谢您对此问题的任何帮助。

修改

现在我已经使我的捕获图像变得更大了,我再次必须使这些值更小,以便它不会返回null。现在值不能大于150,150

1 个答案:

答案 0 :(得分:0)

所以我设法通过简单地从

切换来解决这个问题
BitmapFactory.decodeFileDescriptor(descriptor, null, options);

为:

BitmapFactory.decodeStream(fileInputStream, null, options);

我不知道为什么这会产生如此大的差异但确实如此,图像输出的质量是完美的,几乎没有质量损失,没有内存问题。

我的完整代码如下:

解码:

public static Bitmap decodeSampledBitmap(File file, int reqWidth, int reqHeight) throws FileNotFoundException {

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    options.inPreferredConfig = Bitmap.Config.RGB_565;

    BitmapFactory.decodeStream(new FileInputStream(file), null, options);

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

    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(new FileInputStream(file), null, options);
}

计算样本量:

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

    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;

        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

使用:

ImageView imageView = (ImageView) findViewById(R.id.photo_taken);
int width = imageView.getMeasuredWidth();
int height = imageView.getMeasuredHeight();

File file = //get your file
Bitmap bitmap = CameraUtils.decodeSampledBitmap(file, height, width);
imageView.setImageBitmap(bitmap);

注意:我使用height作为宽度,反之亦然,因为我稍后将位图旋转90度。