Bitmap
Drawable,Canvas和Bitmap
- drawable:通用的圖形對象,用于裝載常用格式的圖像,既可以是PNG,JPG,gif這樣的圖像。同時包含13種Drawable類型的可視化對象,StateListDrawable,BitmapDrawable...
- Canvas:畫布,也就是我們可以繪制的區域。提供了drawXXX()等方法來便捷的繪制圖形。
- Bitmap:是一種存儲像素的數據結構,通過這個對象可以得到一系列的圖像屬性。還可以對圖像進行旋轉,切割,放大,縮小等操作。
個人理解:Bitmap是一種數據結構,存儲像素信息。Drawable 儲存的是 對 Canvas 的一系列操作。而 BitmapDrawable 儲存的是「把 Bitmap 渲染到 Canvas 上」這個操作。
Bitmap,BitmapFactory,BitmapFacotry.Options
獲取Bitmap
由于Bitmap的構造方法私有化,所以我們不能在外部直接實例化一個Bitmap對象。我們只能通過BitmapFactory來得到Bitmap對象。
BitmapFractory常用獲取Bitmap的方法:
途徑 | 方法 |
---|---|
從文件中解析 | decodeFile(String pathName, Options), decodeFile(String pathName) |
從res/目錄下解析 | decodeResource(Resources res,int id), decodeResurce(Resources res, int id, Options) |
從字節數組中解析 | 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) |
通過上述表格我們發現,無論是哪一種途徑得到的Bitmap都有一種重載方法的參數列中多了一個BitmapFacotry.Options參數。那么BitmapFacotry.Options是干嘛的呢?
舉個例子,我們為了縮放圖像想要獲取該圖像的大小,那么首先要在代碼中獲取這個圖像的Bitmap對象,然后通過Bitmap.getWidth()和getheight()方法來獲取圖像的大小。但是如果想要獲取一個大圖像的大小,在得到Bitmap對象時會造成oom。這時我們就可以用到BitmapFractory.Options對象的inJustDecodeBounds字段。操作方法:
- 首先獲取一個Options對象,并將inJustDecodeBounds設置為True。
- 然后選擇一種獲取Bitmap途徑的方法,并傳入Options對象。此時該方法返回的Bitmap為null。
- 然后通過Options.outWidth和outHeight來獲取院士圖片的大小
- 通過設置Options.inSampleSize來決定獲取Bitmap時縮小圖像長寬的系數。
- 最后我們把Options實例的inJustDecodeBounds設置為false,并通過該實例獲取大圖像的Bitmap。這樣就防止了OOM
BitmapFactory.Options類有一個參數inSampleSize,該參數為int型,他的值指示了在解析圖片為Bitmap時在長寬兩個方向上像素縮小的倍數。inSampleSize的默認值和最小值為1(當小于1時,解碼器將該值當做1來處理),且在大于1時,該值只能為2的冪(當不為2的冪時,解碼器會取與該值最接近的2的冪)。參考博文高效使用Bitmaps(一) 大Bitmap的加載,BitmapFactory.Options詳解
Bitmap常用方法
- public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream) 將位圖的壓縮到指定的OutputStream,可以理解成將Bitmap保存到文件中!
- format:格式,PNG,JPG等;
- quality:壓縮質量,0-100,0表示最低畫質壓縮,100最大質量(PNG無損,會忽略品質設定)
- stream:輸出流
- 返回值代表是否成功壓縮到指定流!
- void recycle():回收位圖占用的內存空間,把位圖標記為Dead
- boolean isRecycled():判斷位圖內存是否已釋放
- int getWidth():獲取位圖的寬度
- int getHeight():獲取位圖的高度
- boolean isMutable():圖片是否可修改
- int getScaledWidth(Canvas canvas):獲取指定密度轉換后的圖像的寬度
- int getScaledHeight(Canvas canvas):獲取指定密度轉換后的圖像的高度
- Bitmap createBitmap(Bitmap src):以src為原圖生成不可變得新圖像
- Bitmap createScaledBitmap(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src為原圖,創建新的圖像,指定新圖像的高寬以及是否變。
- Bitmap createBitmap(int width, int height, Config config):創建指定格式、大小的位圖
- Bitmap createBitmap(Bitmap source, int x, int y, int width, int
height)以source為原圖,創建新的圖片,指定起始坐標以及新圖像的高寬。 - public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
BitmapFractory.Options字段
- boolean inJustDecodeBounds——如果設置為true,不獲取圖片,不分配內存,但會返回圖片的高寬度信息。
- int inSampleSize——圖片縮放的倍數。如果設為4,則寬和高都為原來的1/4,則圖是原來的1/16。
- int outWidth——獲取圖片的寬度值
- int outHeight——獲取圖片的高度值
- int inDensity——用于位圖的像素壓縮比
- int inTargetDensity——用于目標位圖的像素壓縮比(要生成的位圖)
- boolean inScaled——設置為true時進行圖片壓縮,從inDensity到inTargetDensity。
獲取Bitmap實例
從資源中獲取位圖的方式有兩種:通過BitmapDrawable或者BitmapFactory。
BitmapDrawable
Android支持三種格式的位圖圖像:.png (preferred),.jpg (acceptable), .gif (discouraged)。
括號里的說明,代表這三種格式的圖片在Android中的支持情況,.png格式圖片優先,.jpg格式也可以,但是效果沒有.png好,.gif支持最差。
在構建應用的時候,Bitmap文件可能會被appt工具壓縮自動優化為無損圖像。例如,一個真彩色PNG,不需要超過256的顏色可以被轉換成一個8位PNG和調色板。這將導致一個圖像質量相同,但這需要更少的內存。所以要意識到,在drawable目錄中圖像的二進制文件在構建程序時可以改變。如果你打算讀一個圖像作為字節流并將它轉換成一個位圖,把你的圖片放在在res /raw/文件夾里,在那里他們不會被優化。參考博文Android Drawable Resource學習(二)、BitmapDrawable和Bitmap
獲取BitmapDrawable
- Bitmap file
我們可以直接從res/drawable目錄下的圖片文件(.jpg,.png,.gif)獲取drawable對象,并將其轉型為BitmapDrawable
res/drawable目錄下的圖片文件(.jpg,.png,.gif)編譯資源數據類型:指向BitmapDrawable類型的指針。
- XML Bitmap:
一個XML bitmap是一個在XML文件中定義的指向一個bitmap文件的資源。其效果是作為一個原始位圖文件的別名,并且可以指定一些額外的屬性。<bitmap>是Bitmap XML的根標簽,它有很多屬性設置,實現平鋪、拉伸或保持圖片原始大小,也可以指定對齊方式等效果。可以參考博文Android樣式的開發:drawable匯總篇。
同樣編譯資源類型指向BitmapDrawable類型的指針
Drawable向下轉型
Resources res=getResources();
Drawable drawable = res.getDrawable(R.drawable.file_name);
//實際上這是一個BitmapDrawable對象
BitmapDrawable bitmapDrawable=(BitmapDrawable)drawable;
//可以在調用getBitmap方法,得到這個位圖
Bitmap bitmap=bitmapDrawable.getBitmap();
BitmapDrawable構造方法
InputStream is=res.openRawResource(R.drawable.file_name);
BitmapDrawable bmpDraw=new BitmapDrawable(is);
Bitmap bmp=bmpDraw.getBitmap();
還有其他構造方法,可以查閱官方文檔
Bitmap 2 BitmapDrawable
Drawable drawable = new BitmapDrawable(bitmap);
BitmapFactory
通過上述表格中各種途徑的靜態方法來獲取Bitmap
//res/drawable目錄下資源id獲取
BitmapFactory.decodeResource(res, resId);
//文件路徑獲取
BitmapFactory.decodeFile(pathName);
//輸入流獲取
BitmapFactory.decodeStream(inputStream);
字節流
從字節流獲取Bitmap
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
Bitmap轉換為字節流
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)方法里有一個參數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,其實所有的可見色都是右紅綠藍組成的,所以紅綠藍又稱為三原色,每個原色都存儲著所表示顏色的信息值。位圖位數越高代表其可以存儲的顏色信息越多,當然圖像也就越逼真。
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圖片壓縮質量參數Bitmap.Config RGB_565等的含義
Android基礎入門教程——8.2.1 Bitmap(位圖)詳解
高效使用Bitmaps(一) 大Bitmap的加載,BitmapFactory.Options詳解
【Android】Drawable、Bitmap、Canvas、Paint之間區別
目標
- 圖片的兩種解決OOM問題