一. BitmapFactory.Options 中inSampleSize的取值问题
inSampleSize 设置大于 1 : 如果值大于 1 , 那么就会缩小图片 ;
解码器操作 : 此时解码器对原始的图片数据进行子采样 , 返回较小的 Bitmap 对象 ;
样本个数 : 样本的大小是在两个维度计算的像素个数 , 每个像素对应一个解码后的图片中的单独的像素点 ;
样本个数计算示例 :
如果 inSampleSize 值为 2 , 那么宽度的像素个数会缩小 2 倍 , 高度也会缩小两倍 ;整体像素个数缩小 4 倍 , 内存也缩小了 4 倍 ;
小于 1 取值 : 如果取值小于 1 , 那么就会被当做 1 , 1 相当于 2 的 0 次方 ;
取值要求 : 该值必须是 2 的幂次方值 , 2 的次方值 , 如 1 , 2 , 4 , 8 , 16 , 32
如果出现了不合法的值 , 就会就近四舍五入到最近的 2 的幂次方值
关于inSampleSize的取值问题Google已经给出了一个推荐的算法:(https://developer.android.com/topic/performance/graphics/load-bitmap)
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;
}
实际测试下还好,基本可以满足不OOM的需求,但是隐隐觉得当inSampleSize的值很大的时候,图片的压缩质量会不会太严重?比如说App内中的相册功能,采用这个算法放大的时候,图片会不会变得很不清楚?一时也没有找到特别好的压缩算法。
二. 图片的放置问题
按照Google给出的示例代码,使用inSampleSize前要先把 options.inJustDecodeBounds = true; 设置成true:
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);
}
然后再计算出inSampleSize,最后再进行decode,个人觉得这段代码还是有缺陷,拿我的手机来说吧,分辨率是14402560, 需要显示的ImageView宽度是1440810,需要加载的图片是1920*1080,通过上面Google的算法,算出inSampleSize的值为1,我把图片放置到xxxhdpi和xxhdpi的时候图片可以正常显示,但是我把图片放到mdpi和raw文件夹下的时候,程序一运行就Crash了,因为inSampleSize的默认值就是1,等于没有做任何处理,但是系统在加载时却会对图片再进行放大,一旦需要申请的字节数过多,系统就直接Crash了:
java.lang.RuntimeException: Canvas: trying to draw too large(132710400bytes) bitmap.
所以我觉得为了保险起见,最好在上面的代码中加上这么一句: options.inScaled = false;
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; options.inScaled = false;
return BitmapFactory.decodeResource(res, resId, options);
}
保证不管我放置在任何文件夹,图片都不会被缩放。
来源:https://www.cnblogs.com/yongdaimi/p/11120590.html
https://cloud.tencent.com/developer/article/2247083
文章讨论了Android开发中BitmapFactory.Options的inSampleSize属性如何影响图片加载,解释了其计算方法以减少内存消耗,防止OOM。同时指出Google推荐算法可能存在的问题,当inSampleSize值较大时可能影响图片质量。此外,文中提到了一个潜在的崩溃风险,即图片在不同密度资源目录下可能导致系统自动缩放,建议设置inScaled为false来避免不必要的缩放操作。

531

被折叠的 条评论
为什么被折叠?



