【Android】Bitmap.Config属性解析与图片格式的区别

    录(本篇字数:2633)

介绍

图片格式介绍

PNG格式 

JPEG格式  

WEBP格式 

· 位图参数介绍

ALPHA_8

RGB_565

ARGB_8888

RGBA_F16


  • 介绍

    android UI中最离不开的就是图片了,图片可以由很多种格式构成,比如png、jpeg、webp格式等等。我们有时候会发现同一张的图片却有不同的大小,即使在图片的宽、高一致的情况下,也会有所差别。这个就是图片内部储存结构导致的,今天我们通过Bitmap.Config下的属性类型让学习一下位图是如何存储的,确切的说它的内部是按怎样的一种规格储存。然后,你就会明白为何有这样的差异了。

    我们最常见的创建一张位图的操作如下,但是一般不会去设置带有Config的类型。

//创建一个Bitmap时,在它的参数里有一个Config
Bitmap.createBitmap(...,Config);
  • 图片格式介绍

    首先,我们来看看Bitmap几个参数类型的源码:

这里的源码是设置它的压缩类型,有3种可以选择,也是计算机中图片格式里最常见的。

    // 设置压缩格式类型
    public static enum CompressFormat {
        JPEG,
        PNG,
        WEBP;

        private CompressFormat() {
        }
    }
  • PNG格式 

    全称:便携式网络图形(Portable Network Graphics,PNG),它是一种无损压缩的位图图形格式,支持索引、灰度、RGB三种颜色方案以及Alpha通道等特性。最高支持1600万色,支持全透明/半透明,也包括复杂的图片透明。它的最大特点应该就是无损压缩,这也使得它拥有丰富的颜色显示效果,即使在压缩情况下也能做到不降低图像质量。

  • JPEG格式  

    全称:(Joint Photographic Experts Group,JPEG)联合图像专家组的英文缩写,这个我们不用管它。我们在计算机中通常看到的是.JPG的后缀名文件,其实就是它的缩写格式。这是因为在很久以前计算机有这样一个规定,只用3位保存后缀名格式。JPEG是一个压缩标准,又可分为标准JPEG、渐进式JPEG及JPEG2000三种,那么这三种又有很大的区别:

  • 标准JPEG:支持最高级别的压缩,但是压缩是有损耗的。此类型图片在网页下载时只能由上而下依序显示图片,直到图片资料全部下载完毕,才能看到全貌。
  • 渐进式 JPEG:标准JPEG的改良格式,可以在网页下载时,先呈现出图片的粗略外观后,再慢慢地呈现出完整的内容,渐进式JPG的文件比标准JPG的文件要来得小。
  • JPEG2000:新一代的影像压缩法,压缩品质更好,其压缩率比标准JPEG高约30%左右,同时支持有损和无损压缩。一个极其重要的特征在于它能实现渐进传输,即先传输图像的轮廓,然后逐步传输数据,让图像由朦胧到清晰显示。
  • WEBP格式 

    WebP格式,Google在2010年推出的新一代图片格式,也是Google开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器宽带资源和数据空间。WebP既支持有损压缩也支持无损压缩。相较编码JPEG文件,编码同样质量的WebP文件需要占用更多的计算资源。

    谷歌浏览器已经支持webp格式,Opera在版本号Opera11.10后也增加了支持,然而火狐和ie暂时还不支持webp格式。当然,Android系统也已经支持了,IOS还尚未支持。

· 位图参数介绍

    前面我们介绍了Android的三种位图存储的格式,下面我们来通过源码解读位图的配置属性。当然,英文好的你看这些注释就可以直观的知道它们的一些区别和作用,但是我还是简单的介绍一下以及举例说明一下。

    这是我们Bitmap.Config的属性,它是由一个enum(枚举)类型构成的,其中拥有6中枚举可以选择。我们选择其中最常用的4个来着重说明一下。下面是Bitmap.Config的源码:

    /**
     * Possible bitmap configurations. A bitmap configuration describes
     * how pixels are stored. This affects the quality (color depth) as
     * well as the ability to display transparent/translucent colors.
     */
    public enum Config {
        // these native values must match up with the enum in SkBitmap.h

        /**
         * Each pixel is stored as a single translucency (alpha) channel.
         * This is very useful to efficiently store masks for instance.
         * No color information is stored.
         * With this configuration, each pixel requires 1 byte of memory.
         */
        ALPHA_8     (1),

        /**
         * Each pixel is stored on 2 bytes and only the RGB channels are
         * encoded: red is stored with 5 bits of precision (32 possible
         * values), green is stored with 6 bits of precision (64 possible
         * values) and blue is stored with 5 bits of precision.
         *
         * This configuration can produce slight visual artifacts depending
         * on the configuration of the source. For instance, without
         * dithering, the result might show a greenish tint. To get better
         * results dithering should be applied.
         *
         * This configuration may be useful when using opaque bitmaps
         * that do not require high color fidelity.
         */
        RGB_565     (3),

        /**
         * Each pixel is stored on 2 bytes. The three RGB color channels
         * and the alpha channel (translucency) are stored with a 4 bits
         * precision (16 possible values.)
         *
         * This configuration is mostly useful if the application needs
         * to store translucency information but also needs to save
         * memory.
         *
         * It is recommended to use {@link #ARGB_8888} instead of this
         * configuration.
         *
         * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
         * any bitmap created with this configuration will be created
         * using {@link #ARGB_8888} instead.
         *
         * @deprecated Because of the poor quality of this configuration,
         *             it is advised to use {@link #ARGB_8888} instead.
         */
        @Deprecated
        ARGB_4444   (4),

        /**
         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
         * for translucency) is stored with 8 bits of precision (256
         * possible values.)
         *
         * This configuration is very flexible and offers the best
         * quality. It should be used whenever possible.
         */
        ARGB_8888   (5),

        /**
         * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
         * for translucency) is stored as a
         * {@link android.util.Half half-precision floating point value}.
         *
         * This configuration is particularly suited for wide-gamut and
         * HDR content.
         */
        RGBA_F16    (6),

        /**
         * Special configuration, when bitmap is stored only in graphic memory.
         * Bitmaps in this configuration are always immutable.
         *
         * It is optimal for cases, when the only operation with the bitmap is to draw it on a
         * screen.
         */
        HARDWARE    (7);

        final int nativeInt;

        private static Config sConfigs[] = {
            null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
        };

        Config(int ni) {
            this.nativeInt = ni;
        }

        static Config nativeToConfig(int ni) {
            return sConfigs[ni];
        }
    }
public enum Config {

        ALPHA_8     (1),
    
        RGB_565     (3),
 
        RGBA_F16    (6),

        ARGB_8888   (5),
    }

    以上4种是我们最常用的属性设置,ARGB_4444头上有个被遗弃的注解,所以我们就不具体去解释它的属性了。我相信只要你知道了ARGB_8888,那么ARGB_4444也就是同一个道理。

    首先,我们来看一下第一个,也就是ALPHA_8,这种枚举类型是可以充当swith语句中的case条件的,所以枚举用起来也特别方便。优点是在于它是线程安全的单利模式,也支持序列化。缺点就是大量使用会导致性能降低。

  • ALPHA_8

    根据上面的源码注释,我简单的概括它的属性信息。首先,它是每个像素储存一个透明度值,每个像素是占1个字节(8位),也就是后面8的由来。其次,它不储存任何颜色信息,只单纯做透明度的处理。

    根据变量名称,我们可以初步的知道它要表达的信息,以下也是如此。

  • RGB_565

    RGB_565,如变量名所述。R代表Red,G代表Green,B代表Blue。那么565就是储存它们的方式,它的每个像素占用2个字节。红色占5位,绿色占6位,蓝色占5位(5位保存的值2的5次方也就是32种的可能性,比如00001,00002...。同理6位则有64种值)。虽然它能提供这么多种颜色值,但是唯独不可以透明。因为它没有提供保存透明度的通道,所以通常它用于一些不透明的图片的设置。

  • ARGB_8888

    我已经说明了两个例子,相信这个你自己也可以看懂的。也如其名,它提供了颜色和透明度的通道,综合了以上两种方式。它每个像素占用4个字节(显然图片的大小也增加),并且它每个都用8位来保存其颜色和透明度值。我们知道8位将有256种可能值,这意味着它的颜色值的可能性越多,图片的质量、显示效果将大大提高。所以,这也是被推荐的一种属性设置。

  • RGBA_F16

    这个与上面变量名又有点区别,从F16就可以看出。它每个像素占用8个字节,但是它是以半浮点数存储的,那前面的F就说的通了。Google的注释里还指明这个属性非常适合用于广色域宽屏和HDR(高动态范围的图片)。所以以此来看,它所占用的内存是最高的,因此显示的效果也非常好。

举个小例子:

    比如拿ARGB_8888来说,它所拥有的颜色种类就是红色:2^8,绿色:2^8,蓝色:2^8,也就是大约1600多万种颜色。这么多种颜色组成的一张图片,比如1920*1080像素的一张图,以ARGB_8888的方式来存储颜色值的话。那它的大小就是1920*1080*4(字节) = 8294400(bytes) =  7.91兆(M)大约值。

    当然,如果用RGBA_F16的方式储存颜色值,那将在16M左右的一张图,这对手机来说已经是一张非常高清的图片了。

©原文链接:https://blog.csdn.net/smile_Running/article/details/82019352

@作者博客:_Xu2WeI

@更多博文:查看作者的更多博文

posted @ 2018-08-24 15:17  爱写Bug的程序猿  阅读(1080)  评论(0编辑  收藏  举报