Bitmap.Config 說明 ALPHA_8 ARGB_4444 ARGB_8888 RGB_565


這篇文章的目的是了解Bitmap.Config

你可以在使用這個方法的時候會遇到

Bitmap android.graphics.Bitmap.createBitmap(int width, int height, Config config)

需要一個Bitmap 然后在上面畫一些東西。

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);

        final int nativeInt;

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

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

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

 

第一眼看上去應是個類類型,上來new一個吧。但是不行。

點進去看是枚舉類型。

 

再仔細看一下源碼:

    public enum Config {
       
        ALPHA_8     (1),
        @Deprecated
        ARGB_4444   (4),
        ARGB_8888   (5);

        final int nativeInt;

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

        Config(int ni) {
            this.nativeInt = ni;
        }
        static Config nativeToConfig(int ni) {
            return sConfigs[ni];
        }
    }

有點蒙逼吧。這語言平見也少用。其實枚舉類型類似於常量,直接用就行。如下:

Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);

好吧,枚舉這東西用得少,可以復習一下。

https://www.cnblogs.com/happyPawpaw/archive/2013/04/09/3009553.html

順便多說兩句,為什么要用枚舉。

枚舉在java1.5以后才推薦使用。

1.switch

JDK1.6之前的switch語句只支持int,char,enum類型,使用枚舉,能讓我們的代碼可讀性更強。

2.使用static final int 來定義常量同樣可以實現邏輯,為什么搞個枚舉出來

  速度更快:

  1 作者:ccloomi
  2 鏈接:https://www.zhihu.com/question/48915384/answer/151489315
  3 來源:知乎
  4 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
  5 
  6 事實上使用枚舉類型的性能幾乎是使用靜態類的16倍,至於為什么我們看代碼,這里我寫了兩個類,Age類是一個枚舉類型public enum Age {
  7     _12,_16,_19
  8 }
  9 AG類是一個靜態類public class AG {
 10     public static final int _12=12;
 11     public static final int _16=16;
 12     public static final int _19=19;
 13 }
 14 然后是一個測試Main類public class Main {
 15     public void age(Age ag){
 16         switch (ag) {
 17         case _12:
 18             break;
 19         case _16:
 20             break;
 21         case _19:
 22             break;
 23         default:
 24             break;
 25         }
 26     }
 27     public void age(int ag){
 28         switch (ag) {
 29         case 12:
 30             break;
 31         case 16:
 32             break;
 33         case 19:
 34             break;
 35         default:
 36             break;
 37         }
 38     }
 39     public static void main(String[] args) {
 40         long t=0,limit=1000000;
 41         Main mm=new Main();
 42         
 43         t=System.currentTimeMillis();
 44         for(long i=0;i<limit;i++){
 45             mm.age(Age._16);
 46         }
 47         System.out.println("耗時"+(System.currentTimeMillis()-t)+"ms");
 48         
 49 
 50         t=System.currentTimeMillis();
 51         for(long i=0;i<limit;i++){
 52             mm.age(16);
 53         }
 54         System.out.println("耗時"+(System.currentTimeMillis()-t)+"ms");
 55     }
 56 }
 57 同樣的方法我們執行100萬此,執行結果耗時0ms
 58 耗時16ms
 59 使用枚舉類的方法秒殺了靜態類,至於為什么我們可以看Main這個方法編譯后生成的字節碼 // access flags 0x1
 60   public age(Lcom/test/en/Age;)V
 61    L0
 62     LINENUMBER 11 L0
 63     INVOKESTATIC com/test/en/Main.$SWITCH_TABLE$com$test$en$Age ()[I
 64     ALOAD 1
 65     INVOKEVIRTUAL com/test/en/Age.ordinal ()I
 66     IALOAD
 67     TABLESWITCH
 68       1: L1
 69       2: L2
 70       3: L3
 71       default: L4
 72    L1
 73     LINENUMBER 13 L1
 74    FRAME SAME
 75     GOTO L4
 76    L2
 77     LINENUMBER 15 L2
 78    FRAME SAME
 79     GOTO L4
 80    L3
 81     LINENUMBER 17 L3
 82    FRAME SAME
 83     GOTO L4
 84    L4
 85     LINENUMBER 21 L4
 86    FRAME SAME
 87     RETURN
 88    L5
 89     LOCALVARIABLE this Lcom/test/en/Main; L0 L5 0
 90     LOCALVARIABLE ag Lcom/test/en/Age; L0 L5 1
 91     MAXSTACK = 2
 92     MAXLOCALS = 2
 93 
 94   // access flags 0x1
 95   public age(I)V
 96    L0
 97     LINENUMBER 23 L0
 98     ILOAD 1
 99     LOOKUPSWITCH
100       12: L1
101       16: L2
102       19: L3
103       default: L4
104    L1
105     LINENUMBER 25 L1
106    FRAME SAME
107     GOTO L4
108    L2
109     LINENUMBER 27 L2
110    FRAME SAME
111     GOTO L4
112    L3
113     LINENUMBER 29 L3
114    FRAME SAME
115     GOTO L4
116    L4
117     LINENUMBER 33 L4
118    FRAME SAME
119     RETURN
120    L5
121     LOCALVARIABLE this Lcom/test/en/Main; L0 L5 0
122     LOCALVARIABLE ag I L0 L5 1
123     MAXSTACK = 1
124     MAXLOCALS = 2
125 注意看使用枚舉類的方法使用的是TABLESWITCH
126 使用靜態類的方法使用的確是LOOKUPSWITCH
127 這兩個性能差距是很大的
View Code

 通過注解,來約束一些變量及參數。使的程序在編寫之時就變得健壯。

 

回到主題:

 

看看枚舉變量倒底什么含義。
public static final Bitmap.Config  ALPHA_8 
public static final Bitmap.Config  ARGB_4444  
public static final Bitmap.Config  ARGB_8888
public static final Bitmap.Config  RGB_565 


ALPHA_8 
源碼注釋很清楚:
/**
* 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 通道值,就是透明值。
Each pixel is stored as a single translucency (alpha) channel
對處理遮罩很有效,
No color information is stored.
沒有存顏色值就是說沒有rgb信息。 (此處畫重點)
each pixel requires 1 byte of memory
每個pixel占一個byte.1個字節。
所以網上很多博文瞎扯的。還是自己看源碼靠譜。

再看下RGB_565
/**
* 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.
*/
每個像素2byte存儲空間。
紅:5位(5 bits)對應32色。就是有32種不同的紅色。
綠:green is stored with 6 bits of precision (64 possible)綠 6 位 64色。
藍:5位 32色

自然沒有alpha值。看明白了沒有透明值。自己去建一個沒有透明bitmap試一下吧,看看什么效果。
最后使用在do not require high color fidelity (圖片質量要求不高的場景)

能表示多少種顏色呢 32*64*32 =65536 色。是不是很熟啊。

再看下
ARGB_4444
/**
* 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.
*/
不再多說了,很好理解,共2byte 16位 。4位透明,R,G,B各占四位。

ARGB_8888   

顧名思義:A8位,G,R,B各8位。

32位真彩色是什么意思呢就是這個類型來表示,一共能表示多少種色彩呢
2^8*2^8*2^8 = 16777216 ;
這里所說的所有東西都是針對一個像素來討論的。
那么一張圖,在內存當中占多少內存呢,
內存=寬*高*每個像素點占的存。
以argb_8888為例:
100*100像素的圖片在內存中占:100*100*32 bit 0.305M
看看滿屏一張圖占多少,1920*1080*32=63.28M
是不是很恐怖呢63M!!!







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM