Android图片压缩及加载总结

目录

一、前言

图片是一个神奇的东西,它不像普通文件一样,在磁盘是占用5KB,加载到内存中也占用5KB,它往往是远超5KB的内存的。为什么会出现这种现象呢?这主要是因为图片是用来展示的,它的每个像素点都是要占用内存空间的。

在网络上会经常见到先压缩再加载图片的代码,比如使用图片质量压缩法,通过加载出来的图片看,确实是起作用了,因为图片的质量降低了,但事实真的如此吗?加载到内存中的图片占用的内存空间真的有减少吗?下面就图片加载及压缩作一下介绍。

图片压缩加载示例代码

private Bitmap compressImage(Bitmap image) { 

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 100;
        while ( baos.toByteArray().length / 1024>100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩 
            baos.reset();//重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
            options -= 10;//每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
}

二、图片加载

图片加载面临的主要问题是占用内存过多,导致卡顿、引发OOM等。图片在内存中所占用的空间大小由其像素点x每个像素点占用字节数决定。所以减少图片占用内存有两个方式,一个是减少图片的像素,另一个是减小每个像素占用字节数。

减少图片像素

  • 增大采样率inSimaleSize
  • 局部加载

增大采样率inSampleSize

假设一张图片是320×160像素,即长是320个像素,宽是160个像素。设置inSampleSize=2,则长的像素为160,宽的像素为80,也就是从长320个像素中,每两个像素中取一个像素,宽也是一样。这样总的像素为会变成160×80,像素减少为原图的1/4。

public Bitmap decodeFile(String imagePath, int width, int height) { 

    /** * 计算采样因子: * 1. 取图片长宽与View长度的比值中较大的那个,以保证图片的内容都会被展示出来 * 2. 取较小的那个,可以保证View被图片内容充满 */

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imagePath, options);

    int sampleSize = 1;
    int imageWidth = options.outWidth;
    int imageHeight = options.outHeight;
    if (imageHeight > height || imageWidth > width) { 
        int hRatio = Math.round((float) imageHeight / height);
        int wRatio = Math.round((float) imageWidth / width);
        sampleSize = Math.max(hRatio, wRatio);
    }

    options.inJustDecodeBounds = false;
    options.inSampleSize = sampleSize;
    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
    return bitmap;
}

局部加载

即只展示图片中的部分内部,可以通过拖动图片来查看图片的其他部分内容。局部加载可以使用BitmapRegionDecoder进行图片的局部解码并展示。

减小每个像素占用字节数

inPreferredConfig参数可以设置图片的色彩模式。设置inPreferredConfig为ALPHA_8,则每个像素占用1个字节,但没有色彩信息;设置为RGB_565,则每个像素占用2个字节;设置为ARGB_4444,每个像素也是占用2个字节;默认是ARGB_8888,每个像素占用4个字节。所以设置不同的样式,可以不同程度来减少内存占用。

public Bitmap decodeFile(String imagePath, int width, int height) { 
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
    return bitmap;
}

RGB

RGB是构成多种颜色的三基色(红绿蓝),也称加成色,主要是图像的采集和显示。

  • RGB_565
  • ARGB_4444
  • ARGB_8888

YUV

与我们熟知的RGB类似,YUV也是一种颜色编码方式,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计可以很好地解决彩色电视与黑白电视的兼容问题,并且,YUV不像RGB那样要求有一个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。
YUV是优化彩色视频信号的编码和传输,和RGB相比,YUV占用的带宽更少。

YUV格式有两大类:planar和packed
对于planar的YUV,先连续存储所有的像素点Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV,每个像素的Y、U、V是连续交叉存储的。

YUV中Y表示的是亮度(Luminance或Luma),也就是灰度值。UV表示的色度(Chrominance或Chroma),作用是描述影像的色彩及饱和度,分别使用Cr、Cb表示。其中,Cr是RGB输入信息的红色部分和RGB信号的亮度值的差异。而Cb反映的是RGB输入信号的蓝色部分和RGB的信息亮度值之间的差异。

  • YUV444
  • YUV422
  • YUV420

YUV444每个像素点进行一次采样;YUV422每2个像素点进行一次采样;YUV420每4个相邻的像素点进行一次采样。
《Android图片压缩及加载总结》

YUV444

每一个Y对应一组UV分量。

YUV422

每两个Y共用一组UV分量。

《Android图片压缩及加载总结》

YUV420

每四个Y共用一组UV分量。

《Android图片压缩及加载总结》

YUV与RGB的关系

RGB转YUV

Y =  0.299*R + 0.587*G + 0.114*B;
U = -0.169*R - 0.331*G + 0.5  *B;
V =  0.5  *R - 0.419*G - 0.081*B;

YUV转RGB

R = Y + 1.4075 * V;
G = Y - 0.3455 * U - 0.7169*V;
B = Y + 1.779 * U;

三、图片压缩

图片压缩主要解决图片占用磁盘空间的大小的问题,使用更小的空间来存储更多的图片信息,一般可以采用高效的压缩算法。图片压缩可分为有损压缩和无损压缩。使用有损压缩对图片压缩后,再次还原时,原图的信息会存在部分丢失,导致图片展示的不如原图丰富,如质量压缩、采样率压缩等;而使用无损压缩后,再次还原图片时,可以完整给还原图片细节,不会有任何丢失。

  • 质量压缩
  • 采样率压缩
  • 其他高效压缩算法

四、图片压缩与图片加载的关系

图片压缩要解决的问题是图片占用磁盘空间的大小,图片加载要解决的问题图片占用内存大小。正常的图片压缩后,其像素点没有变化,所以压缩操作对于图片加载中内存占用没有任何影响。像质量压缩法,图片的质量降低了,但像素依然是那么多,但每个像素包含的信息却减少了,未压缩前可能一个像素代表了一个色彩值,而压缩后,可能多个像素代码了一个色彩值。

如果图片压缩改变了图片大小,如减少了图片的像素点,则压缩操作对图片加载占用内存是有影响的。

    原文作者:mushanshui
    原文地址: https://blog.csdn.net/mushanshui/article/details/122851007
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞