黑马程序员技术交流社区

标题: 【必会】Android中加载高清大图及图片压缩方式 [打印本页]

作者: Android_Robot    时间: 2016-5-27 16:56
标题: 【必会】Android中加载高清大图及图片压缩方式
本帖最后由 Android_Robot 于 2016-10-19 14:55 编辑

【必会】Android中加载高清大图及图片压缩方式

        关于Android中加载高清大图的问题,我们都知道如果我们直接加载原图的话,一个是非常慢,需要等待一定时间,如果没有在一定的时间内给用户响应的话,将会极大影响用户的体验。另一个是如果你的手机内存小的话,可能会直接崩溃。这也就是直接加载高清原图问题。遇到这些问题很容易想到的一点就是图片压缩,本篇文章也就是讲述图片压缩方式来实现加载高清大图的效果。但是现在问题就来了,通过上篇博客我们知道,手机的分辨率有很多,如何保证我同一张图片在不同分辨率的手机上能适当的压缩比例显示出来呢???有的人就直接压缩小点,那么就可以在不同的多个分辨率的手机上显示出来。但是我们都知道压缩的越小,失真率就越高。很容易理解,大部分我们使用的都是位图,位图有一个特点就是有很多个像素点组成的像素矩阵,当我们压缩图片时就相当于像素点,本来显示这张图片需要720*1280个像素点,现在压缩成320*480个像素点,这么少的像素点不足以显示出原来的效果,最后明显造成图片显示不清楚。所以找到一个合适的压缩比例就显得尤为重要了。

  那我们如何做呢?实现的大致思路如下:我们所谓的压缩实际上就是去设置BItmap中的一个inSampleSize(采样率)属性,通过它实现图片的压缩。怎么样去给inSampleSize属性设置一个合适的值呢??首先因为屏幕的分辨率多样化,然后我的图片要根据不同分辨率来得到不同inSampleSize,这样才会合适显示在我的手机屏幕上。所以需要获得屏幕的高度和宽度,然后再去拿到屏幕高度和宽度。然后用图片的宽度,高度分别去除以屏幕的高度和宽度,最后就得到高度比例和宽度比例。

到这里就会出现两种方法来实现压缩:一种比较繁琐,另一种更直接。
  首先,说第一种压缩方式。
      由于图片大多数都是位图显示,即具体个数的像素点来显示的,在不同分辨率的手机屏幕显示图片说白就是在不同像素点的总数的屏幕中显示,很容易理解,当我有个很大的图片,所谓很很大的图片 就是总的像素点数很多,并且在低分辨(总的像素点少显示)肯定有问题,只能显示部分,所以需要 根据当前的手机分辨率的大小,来适当压缩图片的大小比例,然后来显示在相应分辨率的屏幕上当我通过某个方式拿到一张图片会有如下几种情况:  图片宽度(ImWidth),图片高度(ImHeight),屏幕宽度(Width),屏幕高度(Height)
        
      1、若图片的宽度大于图片高度(即横向图片),且宽度大于屏幕宽度:Size=ImWidth/Width
      2、若图片的高度大于图片宽度(即纵向图片),且高度大于屏幕高度:Size=ImHeight/Height;
      3、就是根据一个图片压缩比例算法公式:取图片宽度压缩倍数和图片高度的压缩倍数的平均值:Size=(ImWidth/Width+ImHeight/Height)/2;
最后将我们在不同情况下得到的size赋给我们的inSampleSize。
       然后,说第二种,第二种就更直接暴力,直接给出一个公式:
                      inSampleSize=Math.sqrt(widthScaleSize*widthScaleSize+heightScaleSize*heightScaleSize);
这个公式有点像数学上的勾股定理,但是自己想想挺有道理,它这样取这么一个inSampleSize,其实类似就是去对角线的压缩比。
最后再来说一种方式,这个叫图片质量的压缩,就是在我们压缩图片过程,如何尽量保证我们的图片的质量呢??主要是通过Bitmap的compress来实现质量的压缩的。不妨我们来看下源码是怎么介绍的。
    /**
     * Write a compressed version of the bitmap to the specified outputstream.
     * If this returns true, the bitmap can be reconstructed by passing a
     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
     * all Formats support all bitmap configs directly, so it is possible that
     * the returned bitmap from BitmapFactory could be in a different bitdepth,
     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
     * pixels).
     *
     * @param format   The format of the compressed image
     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
     *                 small size, 100 meaning compress for max quality. Some
     *                 formats, like PNG which is lossless, will ignore the
     *                 quality setting
     * @param stream   The outputstream to write the compressed data.
     * @return true if successfully compressed to the specified stream.
     */
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos)
      它大致的意思是这样的就是将一个Bitmap对象保存在一个确定的输出流中,并且compress会返回一个boolean类型的值,如果返回为true就会通过一个与之相对应的输入流来重建一个BItmap对象,然后标注了:并不是所有的格式都直接支持这种方式,这样就会造成出来不同尺寸大小BItmap可能会失去原有图片像素的透明度。力例如JPEG格式图片仅仅支持不透明像素点。还需要注意:就是里面quality参数的介绍:它是这样说的quatily取值范围为:0到1000代表质量最低,100则代表质量最高,如果是PNG格式的图片的话,忽视了质量值的设置,就会造成图片的失真。
      那么有了以上的了解,相信对下面代码的理解更加简单了。
运行结果:
其他精华资源推荐:
【强荐!】2016年最新Android学习路线图——按此路线图学习月薪过万{ 火速收入}
作者: miqideliwu    时间: 2016-7-29 00:26
早晚会用到哈,谢谢
作者: fzc123    时间: 2016-7-29 00:44
嗯就是这样好好好不明觉厉
作者: Frank_Ms1ZR    时间: 2016-7-29 06:16
谢谢分享
作者: ゛Babyゝ    时间: 2016-7-29 08:45
赞赞赞
作者: 13182002757    时间: 2016-7-29 08:48
学习一下
作者: 646721826    时间: 2016-7-29 17:05
先学着计多不压身
作者: xyy123456    时间: 2016-7-30 09:40
专业呀,先学习学习
作者: 林哲生10    时间: 2016-7-30 22:30
早晚会用到的,先收藏了!
作者: blackhorse1    时间: 2016-7-30 23:11
专业啊,佩服
作者: fangyue    时间: 2016-8-1 00:19
必须赞一个
作者: 修身丶丶丶    时间: 2016-8-1 10:58
每天保持好心情
作者: yanzhipenglai    时间: 2016-8-1 21:59
多学了一招 谢过版主
作者: flyliou    时间: 2016-8-1 23:27
这个虽然不太懂但是感觉很强大的样子
作者: belowfox    时间: 2016-8-2 14:48
先顶起来再看~~
作者: 正哥敲代码    时间: 2016-8-2 22:35
谢谢回头会用到的
作者: lmdfgjl    时间: 2016-8-2 23:05
有用,不错,留着了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2