初識Android Bitmap

Bitmap

Drawable,Canvas和Bitmap

  • drawable:通用的圖形對象系谐,用于裝載常用格式的圖像讨跟,既可以是PNG晾匠,JPG凉馆,gif這樣的圖像亡资。同時包含13種Drawable類型的可視化對象锥腻,StateListDrawable,BitmapDrawable...
  • Canvas:畫布京革,也就是我們可以繪制的區(qū)域匹摇。提供了drawXXX()等方法來便捷的繪制圖形廊勃。
  • Bitmap:是一種存儲像素的數(shù)據(jù)結(jié)構(gòu)供搀,通過這個對象可以得到一系列的圖像屬性。還可以對圖像進(jìn)行旋轉(zhuǎn)胎源,切割屿脐,放大的诵,縮小等操作。

個人理解:Bitmap是一種數(shù)據(jù)結(jié)構(gòu)烦粒,存儲像素信息扰她。Drawable 儲存的是 對 Canvas 的一系列操作徒役。而 BitmapDrawable 儲存的是「把 Bitmap 渲染到 Canvas 上」這個操作窖壕。

Bitmap瞻讽,BitmapFactory,BitmapFacotry.Options

獲取Bitmap

由于Bitmap的構(gòu)造方法私有化晌砾,所以我們不能在外部直接實例化一個Bitmap對象贡羔。我們只能通過BitmapFactory來得到Bitmap對象个初。

BitmapFractory常用獲取Bitmap的方法:

途徑 方法
從文件中解析 decodeFile(String pathName, Options), decodeFile(String pathName)
從res/目錄下解析 decodeResource(Resources res,int id), decodeResurce(Resources res, int id, Options)
從字節(jié)數(shù)組中解析 decodeByteArray(byte[] data, int offset, int length), decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts)
從流中解析 decodeStream(InputStream is), decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts)

通過上述表格我們發(fā)現(xiàn)楣嘁,無論是哪一種途徑得到的Bitmap都有一種重載方法的參數(shù)列中多了一個BitmapFacotry.Options參數(shù)逐虚。那么BitmapFacotry.Options是干嘛的呢?

舉個例子撮躁,我們?yōu)榱丝s放圖像想要獲取該圖像的大小买雾,那么首先要在代碼中獲取這個圖像的Bitmap對象,然后通過Bitmap.getWidth()和getheight()方法來獲取圖像的大小嗤军。但是如果想要獲取一個大圖像的大小叙赚,在得到Bitmap對象時會造成oom震叮。這時我們就可以用到BitmapFractory.Options對象的inJustDecodeBounds字段浪慌。操作方法:

  • 首先獲取一個Options對象朴则,并將inJustDecodeBounds設(shè)置為True乌妒。
  • 然后選擇一種獲取Bitmap途徑的方法,并傳入Options對象古掏。此時該方法返回的Bitmap為null槽唾。
  • 然后通過Options.outWidth和outHeight來獲取院士圖片的大小
  • 通過設(shè)置Options.inSampleSize來決定獲取Bitmap時縮小圖像長寬的系數(shù)光涂。
  • 最后我們把Options實例的inJustDecodeBounds設(shè)置為false忘闻,并通過該實例獲取大圖像的Bitmap。這樣就防止了OOM

BitmapFactory.Options類有一個參數(shù)inSampleSize私恬,該參數(shù)為int型本鸣,他的值指示了在解析圖片為Bitmap時在長寬兩個方向上像素縮小的倍數(shù)荣德。inSampleSize的默認(rèn)值和最小值為1(當(dāng)小于1時,解碼器將該值當(dāng)做1來處理)曹傀,且在大于1時皆愉,該值只能為2的冪(當(dāng)不為2的冪時幕庐,解碼器會取與該值最接近的2的冪)家淤。參考博文高效使用Bitmaps(一) 大Bitmap的加載,BitmapFactory.Options詳解

Bitmap常用方法

  • public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream) 將位圖的壓縮到指定的OutputStream絮重,可以理解成將Bitmap保存到文件中青伤!
    • format:格式,PNG号杠,JPG等姨蟋;
    • quality:壓縮質(zhì)量立帖,0-100,0表示最低畫質(zhì)壓縮偷仿,100最大質(zhì)量(PNG無損,會忽略品質(zhì)設(shè)定)
    • stream:輸出流
    • 返回值代表是否成功壓縮到指定流酝静!
  • void recycle():回收位圖占用的內(nèi)存空間别智,把位圖標(biāo)記為Dead
  • boolean isRecycled():判斷位圖內(nèi)存是否已釋放
  • int getWidth():獲取位圖的寬度
  • int getHeight():獲取位圖的高度
  • boolean isMutable():圖片是否可修改
  • int getScaledWidth(Canvas canvas):獲取指定密度轉(zhuǎn)換后的圖像的寬度
  • int getScaledHeight(Canvas canvas):獲取指定密度轉(zhuǎn)換后的圖像的高度
  • Bitmap createBitmap(Bitmap src):以src為原圖生成不可變得新圖像
  • Bitmap createScaledBitmap(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src為原圖讳窟,創(chuàng)建新的圖像敞恋,指定新圖像的高寬以及是否變硬猫。
  • Bitmap createBitmap(int width, int height, Config config):創(chuàng)建指定格式啸蜜、大小的位圖
  • Bitmap createBitmap(Bitmap source, int x, int y, int width, int
    height)以source為原圖,創(chuàng)建新的圖片裹粤,指定起始坐標(biāo)以及新圖像的高寬遥诉。
  • public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
    Matrix m, boolean filter)

BitmapFractory.Options字段

  • boolean inJustDecodeBounds——如果設(shè)置為true突那,不獲取圖片构眯,不分配內(nèi)存惫霸,但會返回圖片的高寬度信息壹店。
  • int inSampleSize——圖片縮放的倍數(shù)硅卢。如果設(shè)為4,則寬和高都為原來的1/4脉顿,則圖是原來的1/16艾疟。
  • int outWidth——獲取圖片的寬度值
  • int outHeight——獲取圖片的高度值
  • int inDensity——用于位圖的像素壓縮比
  • int inTargetDensity——用于目標(biāo)位圖的像素壓縮比(要生成的位圖)
  • boolean inScaled——設(shè)置為true時進(jìn)行圖片壓縮蔽莱,從inDensity到inTargetDensity。

獲取Bitmap實例

從資源中獲取位圖的方式有兩種:通過BitmapDrawable或者BitmapFactory盗冷。

BitmapDrawable

Android支持三種格式的位圖圖像:.png (preferred)同廉,.jpg (acceptable)乓诽, .gif (discouraged)咒程。
括號里的說明帐姻,代表這三種格式的圖片在Android中的支持情況饥瓷,.png格式圖片優(yōu)先呢铆,.jpg格式也可以棺克,但是效果沒有.png好确买,.gif支持最差。

在構(gòu)建應(yīng)用的時候纱皆,Bitmap文件可能會被appt工具壓縮自動優(yōu)化為無損圖像湾趾。例如,一個真彩色PNG芭商,不需要超過256的顏色可以被轉(zhuǎn)換成一個8位PNG和調(diào)色板。這將導(dǎo)致一個圖像質(zhì)量相同搀缠,但這需要更少的內(nèi)存蓉坎。所以要意識到,在drawable目錄中圖像的二進(jìn)制文件在構(gòu)建程序時可以改變胡嘿。如果你打算讀一個圖像作為字節(jié)流并將它轉(zhuǎn)換成一個位圖蛉艾,把你的圖片放在在res /raw/文件夾里,在那里他們不會被優(yōu)化衷敌。參考博文Android Drawable Resource學(xué)習(xí)(二)勿侯、BitmapDrawable和Bitmap

獲取BitmapDrawable

  • Bitmap file
    我們可以直接從res/drawable目錄下的圖片文件(.jpg,.png,.gif)獲取drawable對象助琐,并將其轉(zhuǎn)型為BitmapDrawable

res/drawable目錄下的圖片文件(.jpg,.png,.gif)編譯資源數(shù)據(jù)類型:指向BitmapDrawable類型的指針。

  • XML Bitmap:
    一個XML bitmap是一個在XML文件中定義的指向一個bitmap文件的資源。其效果是作為一個原始位圖文件的別名,并且可以指定一些額外的屬性靴拱。<bitmap>是Bitmap XML的根標(biāo)簽偎窘,它有很多屬性設(shè)置,實現(xiàn)平鋪上祈、拉伸或保持圖片原始大小嗡呼,也可以指定對齊方式等效果。可以參考博文Android樣式的開發(fā):drawable匯總篇

同樣編譯資源類型指向BitmapDrawable類型的指針

Drawable向下轉(zhuǎn)型

Resources res=getResources();  
Drawable drawable = res.getDrawable(R.drawable.file_name);  
//實際上這是一個BitmapDrawable對象  
BitmapDrawable bitmapDrawable=(BitmapDrawable)drawable;  
//可以在調(diào)用getBitmap方法,得到這個位圖  
Bitmap bitmap=bitmapDrawable.getBitmap(); 

BitmapDrawable構(gòu)造方法

InputStream is=res.openRawResource(R.drawable.file_name);
BitmapDrawable bmpDraw=new BitmapDrawable(is);
Bitmap bmp=bmpDraw.getBitmap();

還有其他構(gòu)造方法氧映,可以查閱官方文檔

Bitmap 2 BitmapDrawable

Drawable drawable = new BitmapDrawable(bitmap);

BitmapFactory

通過上述表格中各種途徑的靜態(tài)方法來獲取Bitmap

//res/drawable目錄下資源id獲取
BitmapFactory.decodeResource(res, resId);
//文件路徑獲取
BitmapFactory.decodeFile(pathName);
//輸入流獲取
BitmapFactory.decodeStream(inputStream);

字節(jié)流

從字節(jié)流獲取Bitmap

public Bitmap Bytes2Bimap(byte[] b) {  
    if (b.length != 0) {  
        return BitmapFactory.decodeByteArray(b, 0, b.length);  
    } else {  
        return null;  
    }  
} 

Bitmap轉(zhuǎn)換為字節(jié)流

public byte[] Bitmap2Bytes(Bitmap bm) {  
    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    bm.compress(Bitmap.CompressFormat.PNG, 100, baos);  
    return baos.toByteArray();  
}  

Bitmap.Config

在Bitmap類里createBitmap(intwidth, int height, Bitmap.Config config)方法里有一個參數(shù)Bitmap.Config是用來做什么的呢线召?

要解決Bitmap的OOM問題可以有兩種方法:

  • 壓縮大圖片的大小塔逃,縮放
  • 改變大圖片的色彩存儲方法

那么Bitmap.Config就是圖片存儲顏色。在Bitmap.Config文檔中我們看到四個枚舉變量躏吊。

  • Bitmap.Config : ALPHA_8, 就是Alpha由8位組成
  • Bitmap.Config : ARGB_4444, 就是由4個4位組成即16位,
  • Bitmap.Config : ARGB_8888, 就是由4個8位組成即32位悠菜,
  • Bitmap.Config : RGB_565, 就是R為5位,G為6位,B為5位共16位

ARGB指的是一種色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue,其實所有的可見色都是右紅綠藍(lán)組成的蕴轨,所以紅綠藍(lán)又稱為三原色,每個原色都存儲著所表示顏色的信息值成福。位圖位數(shù)越高代表其可以存儲的顏色信息越多,當(dāng)然圖像也就越逼真。

參考博文android圖片壓縮質(zhì)量參數(shù)Bitmap.Config RGB_565等的含義

Bitmap縮放

public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        float srcWidth = options.outWidth;
        float srcHeight = options.outHeight;

        int inSampleSize = 1;
        if(srcHeight > destHeight || srcWidth > destWidth) {
            if(srcWidth > srcHeight) {
                inSampleSize = Math.round(srcHeight / destHeight);
            } else {
                inSampleSize = Math.round(srcWidth /destWidth);
            }
        }

        options = new BitmapFactory.Options();
        options.inSampleSize = inSampleSize;

        return BitmapFactory.decodeFile(path, options);
    }

參考

android圖片壓縮質(zhì)量參數(shù)Bitmap.Config RGB_565等的含義

Android基礎(chǔ)入門教程——8.2.1 Bitmap(位圖)詳解

高效使用Bitmaps(一) 大Bitmap的加載,BitmapFactory.Options詳解

Android樣式的開發(fā):drawable匯總篇

【Android】Drawable旗扑、Bitmap慈省、Canvas致燥、Paint之間區(qū)別

目標(biāo)

  • 圖片的兩種解決OOM問題
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市床三,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洗做,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蜡塌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)熙宇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門颂郎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陨献,“玉大人皂股,你說我怎么就攤上這事坠宴。” “怎么了绷旗?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵隅忿,是天一觀的道長。 經(jīng)常有香客問我弊仪,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮锐涯,結(jié)果婚禮上磕诊,老公的妹妹穿的比我還像新娘。我一直安慰自己纹腌,他們只是感情好霎终,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著升薯,像睡著了一般莱褒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上覆劈,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天保礼,我揣著相機(jī)與錄音,去河邊找鬼责语。 笑死,一個胖子當(dāng)著我的面吹牛目派,可吹牛的內(nèi)容都是我干的坤候。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼企蹭,長吁一口氣:“原來是場噩夢啊……” “哼白筹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谅摄,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤徒河,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后送漠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顽照,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年闽寡,在試婚紗的時候發(fā)現(xiàn)自己被綠了代兵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡爷狈,死狀恐怖植影,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涎永,我是刑警寧澤思币,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布鹿响,位于F島的核電站,受9級特大地震影響谷饿,放射性物質(zhì)發(fā)生泄漏抢野。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一各墨、第九天 我趴在偏房一處隱蔽的房頂上張望指孤。 院中可真熱鬧,春花似錦贬堵、人聲如沸恃轩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叉跛。三九已至,卻和暖如春蒸殿,著一層夾襖步出監(jiān)牢的瞬間筷厘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工宏所, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留酥艳,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓爬骤,卻偏偏與公主長得像充石,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子霞玄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容