android加载大图处理,Android之解析加载大图

现在的世界是图片的世界,一切都只看如,就像“没图没真相”、“没图你说个XX”

可是图片有这么多,高清图片这么大,Android手机的内存又有限,用有限的内存加载无限大的图片,这是一个很严峻的问题,所以大图加载技术应运而生。

我们先看加载大图的全部代码,然后在细细解析代码的意思吧!

public class MainActivity extends Activity {

private ImageView iv;

private int screenWidth;

private int screenHeight;

@SuppressWarnings("deprecation")

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//[1]找到iv 显示加载图片

iv = (ImageView) findViewById(R.id.iv);

//[2]获取手机的分辨率 获取windowmanager 实例

WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);

// 用于android 8以上

screenWidth = wm.getDefaultDisplay().getWidth();

screenHeight = wm.getDefaultDisplay().getHeight();

// 只能用于android 13以上

//Point outSize = new Point();

//wm.getDefaultDisplay().getSize(outSize);

//screenWidth = outSize.x;

//screenHeight = outSize.y;

System.out.println("手机的宽和高:"+screenWidth+"---"+screenHeight);

}

//点击按钮 加载dog.jpg 这张图片

@SuppressLint("SdCardPath")

public void click(View v) {

//[2]把xxxx.jpg 转换成bitmap

//创建bitmap工厂的配置参数

BitmapFactory.Options options = new Options();

//返回一个null 没有bitmap 不去真正解析位图 但是能返回图片的一些信息(宽和高)

options.inJustDecodeBounds = true;

BitmapFactory.decodeFile("/mnt/sdcard/xxxx.jpg",options);

//[3]获取图片的宽和高

int imgWidth = options.outWidth;

int imgHeight = options.outHeight;

System.out.println("图片的宽:"+imgWidth+"-----"+imgHeight);

//[4]计算缩放比

int scale = 1; //我们定义的缩放比

int scalex = imgWidth/screenWidth;

int scaley = imgHeight /screenHeight;

if (scalex >=scaley&&scalex > scale) {

scale = scalex;

}

if (scaley > scalex && scaley>scale) {

scale = scaley;

}

System.out.println("缩放比为:"+scale);

//[5]按照缩放比显示图片

options.inSampleSize = scale;

//[6]开始真正的解析位图

options.inJustDecodeBounds = false;

Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg",options);

//[7]把bitmap显示到控件上

iv.setImageBitmap(bitmap);

}

}

好了,上面就是解码大图Demo的全部代码了。

我们首先获得屏幕的大小,然后获得图片的大小,最后通过计算屏幕与图片的缩放比,按照缩放比来解析位图。

其中有两个方法比较重要,在这里我们进行解析:

options.inJustDecodeBounds

这一个方法的意思是,如果给它赋值true,那么它就不会解析图片,如果不解析图片,那么我们就不能够将图片展示在手机屏幕之中。

使用它的目的是为了获得图片的一些信息,如图片高度和宽度,然后进行下一步工作,也就是计算缩放比。

重点,在计算好缩放比(options.inSampleSize)之后不要忘记将options.inJustDecodeBounds设置为false,否则仍然不会展示图片。

options.inSampleSize

这一个方法是给图片赋予缩放比,当它的值大于1的时候,它就会按照缩放比返回一个小图片用来节省内存。举个例子,如果她的值为4,那么返回的图片大小将会是原始高度和宽度的1/4大小。

如果它的值小于1的话,不会有任何的效果。

顺便友情提示options.inSampleSize的值最后会按照2的倍数来进行缩放,所以最好将缩放值设置为2的倍数。

关于计算缩放比的问题,在上面的代码中我们是直接通过图片高宽/屏幕高宽计算的,缩放比的值这是通过比较高度缩放比和宽度缩放比,那个数值大就取哪一个。

当然,这不是唯一的算法,也可以制定自己的算法。

补充说明:

计算缩放比,也就是inSampleSize的值的方式被 mcarthorlee 大神批评了,不过大神也说的对,

如果屏幕是1280720,图片大小是1300800,那你算出来的inSampleSize就是1,完全没有缩小。

为了让大家不被我的计算方式误导,这里也放出Android提供的缩放比计算方法:

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;

}

在这个方法中,我们只需要提供图片的元数据options提供进去,然后填入自己想获得图片的宽高的数值,然后就能够计算出缩放比。

Android官方关于加载大图的技术指导:

对大图需要特殊处理的原因

要对大图进行处理除了因为图片大小自身的原因之外,还有Android对图片解码的因素在内。

比如一张宽度2400px,高度为3200px的jpg格式的图片,假设它现在的大小为3mb,但是如果我们直接在android中解码,使用以下代码:

BitmapFactory.decodeFile("bigImage.jpg");

那么结果会怎样呢?

Android在解码这种图片的时候会申请29MB左右的内存来进行解码。

这是怎么回事呢?

因为图片的大小 = 图片总像素 * 图片当个像素的大小

在Android中使用ARGB来展示颜色的,一般情况下使用的是ARGB_8888,每个像素的大小约为4byte。

每个像素4 byte的是ARGB_8888,还有一个ARGB_4444是2 byte,RGB_565也是2 byte。

详情请看官方文档:

所以上面的宽2400px,高3200px的大图在Android中解码出来的大小的计算公式:

2400 * 3200 * 4 = 30720000byte

换算成mb,大小为29mb左右。

这就无怪乎Android需要为加载大图做出特殊的处理了,就这么一张大小为2mb的jpg图片解码出来就有29mb,那么其他图片一起解码出来,Android的内存怎么够用!

以上为作者对Android加载大图的个人理解,如有错漏之处,请不吝赐教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值