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)然圖像也就越逼真。
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】Drawable旗扑、Bitmap慈省、Canvas致燥、Paint之間區(qū)別
目標(biāo)
- 圖片的兩種解決OOM問題