You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将ImageUri转换为Bitmap以实现图片压缩适配ImageView加载要求

ImageUri转Bitmap实现方案

需求背景:需要对图片做压缩处理,ImageView不支持直接加载高分辨率图片,该转换是图片压缩操作的前置步骤。

前置权限要求

  • 访问外部存储图片时,Android 12及以下系统需申请READ_EXTERNAL_STORAGE权限,Android 13及以上系统需申请READ_MEDIA_IMAGES权限
  • 读取应用内Uri、系统媒体库返回的安全Uri无需额外申请权限

核心实现代码

实现逻辑采用先读取图片边界、计算采样率再解码的方式,避免直接加载高分辨率图片导致内存溢出:

Kotlin 实现

fun uriToBitmap(context: Context, uri: Uri): Bitmap? {
    return try {
        // 仅读取图片分辨率,不加载完整图片到内存
        val options = BitmapFactory.Options().apply {
            inJustDecodeBounds = true
        }
        context.contentResolver.openInputStream(uri)?.use { inputStream ->
            BitmapFactory.decodeStream(inputStream, null, options)
        }
        // 可根据实际业务需求调整目标宽高,示例为1080p规格
        val targetWidth = 1080
        val targetHeight = 1920
        options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight)
        options.inJustDecodeBounds = false
        // 按采样率解码得到适配后的Bitmap
        context.contentResolver.openInputStream(uri)?.use { inputStream ->
            BitmapFactory.decodeStream(inputStream, null, options)
        }
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

/**
 * 计算Bitmap采样率,数值为2的n次方,采样率越高输出的Bitmap分辨率越低
 */
private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
    val height = options.outHeight
    val width = options.outWidth
    var inSampleSize = 1
    if (height > reqHeight || width > reqWidth) {
        val halfHeight = height / 2
        val halfWidth = width / 2
        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
            inSampleSize *= 2
        }
    }
    return inSampleSize
}

Java 实现

public Bitmap uriToBitmap(Context context, Uri uri) {
    try {
        // 仅读取图片分辨率,不加载完整图片到内存
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        BitmapFactory.decodeStream(inputStream, null, options);
        inputStream.close();

        // 可根据实际业务需求调整目标宽高,示例为1080p规格
        int targetWidth = 1080;
        int targetHeight = 1920;
        options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight);
        options.inJustDecodeBounds = false;

        // 按采样率解码得到适配后的Bitmap
        InputStream inputStream2 = context.getContentResolver().openInputStream(uri);
        Bitmap bitmap = BitmapFactory.decodeStream(inputStream2, null, options);
        inputStream2.close();
        return bitmap;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

/**
 * 计算Bitmap采样率,数值为2的n次方,采样率越高输出的Bitmap分辨率越低
 */
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    int height = options.outHeight;
    int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        int halfHeight = height / 2;
        int halfWidth = width / 2;
        while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

注意事项

  • 上述实现已经在解码阶段完成了初步的分辨率压缩,无需再单独对原始高分辨率图片做全量加载
  • 得到转换后的Bitmap后,可继续通过质量压缩、格式转换等操作完成后续的图片压缩需求,再加载到ImageView中即可

内容的提问来源于stack exchange,提问作者Shahzad Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 05:57:04