Uri转Bitmap时抛出java.io.IOException: getPixels failed with error invalid scale异常求助
最近我在处理从用户相册导入图片并转换为Bitmap的需求时,刚好撞上了这个一模一样的异常,折腾好一会儿才摸出几个可行的解决方向,分享给碰到同样问题的开发者朋友:
检查缩放参数的合理性
报错里的“invalid scale”大概率和你设置的解码缩放规则有关。比如用ImageDecoder时,如果强制设置的目标尺寸或缩放比例过于极端(比如把100x100的图硬缩放到10000x10000,或者缩放比例设成负数),就可能触发底层解码失败。建议先通过ImageDecoder获取图片原始尺寸,再根据实际需求计算合理的缩放值,别盲目乱设参数。确认Uri的访问权限
虽然报错指向scale,但有时候是读取图片的权限不足,导致底层拿到的图片数据不完整,进而触发了看似无关的解码错误。确保你申请了对应版本的存储权限:Android 12及以下要READ_EXTERNAL_STORAGE,Android 13及以上要READ_MEDIA_IMAGES;另外,获取Uri时尽量用ActivityResultContracts.OpenDocument这类能拿持久化权限的方式,避免临时权限过期的坑。换用BitmapFactory解码方案
如果ImageDecoder的路子一直踩坑,可以试试传统的BitmapFactory结合ContentResolver解码Uri:private Bitmap uriToBitmap(Context context, Uri uri, int targetWidth, int targetHeight) { Bitmap bitmap = null; try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { BitmapFactory.Options options = new BitmapFactory.Options(); // 先获取图片原始尺寸 options.inJustDecodeBounds = true; BitmapFactory.decodeStream(inputStream, null, options); // 计算合适的采样率,避免内存溢出或缩放异常 options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight); options.inJustDecodeBounds = false; // 重新打开输入流进行实际解码 try (InputStream newInputStream = context.getContentResolver().openInputStream(uri)) { bitmap = BitmapFactory.decodeStream(newInputStream, null, options); } } catch (IOException e) { e.printStackTrace(); } return bitmap; } private 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; }这种先拿原始尺寸再设采样率的方式,能更稳妥地控制解码后Bitmap的大小,减少异常概率。
验证图片文件的完整性
偶尔会碰到用户相册里的图片本身损坏或格式异常的情况——虽然相册能正常显示,但转Bitmap时就出错。可以在代码里加个异常捕获后的提示,引导用户换张图片试试,或者用其他图片工具验证这张图能不能正常打开。
如果以上方法都没解决问题,建议打印出图片原始宽高、你设置的缩放参数这些细节,进一步定位到底哪步参数出问题了~
内容来源于stack exchange

