Bitmap是Android中處理圖片的一個重要的類。用它可以獲取圖片信息,進行圖片剪切、平移、旋轉、縮放等操作,並可以指定格式保存圖片文件。
一、 Bitmap對象的獲取
獲取Bitmap主要依靠BitmapFactory類,其API注釋為:Creates Bitmap objects from various sources, including files, streams,and byte-arrays.
即利用文件、數據流和字節數組等資源創建Bitmap對象,主要涉及到以下幾個方法:
//1、通過資源id獲取:
//public static Bitmap decodeResource(Resources res, int id, Options opts){}
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ivTest.setImageBitmap(mBitmap);
//2、通過文件路徑獲取:
//public static Bitmap decodeFile(String pathName, Options opts){}
Bitmap mBitmap = BitmapFactory.decodeFile("/storage/emulated/0/DCIM/Camera/20151130_221159_temp.jpg");
ivTest.setImageBitmap(mBitmap);
//3、通過字節數組獲取:
//public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts){}
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
//4、通過數據流獲取:
//public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts){}
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = 8;
InputStream inputStream = getInputStream("20151005_093444.jpg");
/*private InputStream getInputStream(String fileName) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String SDCarePath = Environment.getExternalStorageDirectory().toString();
String filePath = SDCarePath + File.separator + fileName;
Log.d("HWGT", "filePath..=.."+filePath);
File file = new File(filePath);
try {
FileInputStream fileInputStream = new FileInputStream(file);
return fileInputStream;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}*/
Bitmap mBitmap = BitmapFactory.decodeStream(inputStream,null,bitmapOptions);
ivTest.setImageBitmap(mBitmap);
//關於Options 與inSampleSize 屬性,后文解釋
除了利用BitmapFactory類的decodeXXX()方法外,還有一些獲取bitmap對象的方法,比如:
在android.content.res包下的Resources.java中,
public InputStream openRawResource(int id, TypedValue value)方法可用來間接獲取Bitmap對象:
InputStream is = getResources().openRawResource(R.drawable.ic_launcher); BitmapDrawable bd = new BitmapDrawable(is); Bitmap bm = bd.getBitmap(); //或者 BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(R.drawable.ic_launcher); Bitmap bm = bd.getBitmap();
之上是Bitmap對象的獲取。
二、BitmapFactory.Options
BitmapFactory類中,除了各種用於創建Bitmap對象的方法外,還有一個比較重要的東西,就是BitmapFactory的靜態內部類Options。
其中,有幾個較常用的屬性:
1、inJustDecodeBounds:設置inJustDecodeBounds為true后,調用decodeFile方法時,並不真正分配創建Bitmap所需的空間,適用於僅僅只需要獲取一些屬性——比如原始圖片的長度和寬度等的情況,比如在壓縮圖片時,需要計算屬性inSampleSize的值,就需要獲取原始圖片的長度和寬度。一般步驟如下:
先設置inJustDecodeBounds= true,調用decodeFile()得到圖像的基本信息;利用圖像的寬度(或者高度,或綜合)以及目標寬度(高度),得到inSampleSize值,再設置inJustDecodeBounds= false,調用decodeFile()得到完整的圖像數據。
2、inSampleSize:縮放圖片采用的比率值,設置之后, 將以2的指數的倒數倍對原始圖片進行縮放。
3、inPreferredConfig:設置圖片的色彩模式,可選值為Android.graphics.Bitmap的一個內部類Bitmap.Config的枚舉值:常用ALPHA_8、RGB_565和ARGB_8888,默認是ARGB_8888,其中,A代表透明度,R代表紅色,G代表綠色,B代表藍色
4、inPurgeable:如果設置為true的話,表示在內存空間不足的時候,允許所創建的bitmap被回收。
5、inInputShareable:當inPurgeable被設置為false時,該參數失去意義,當inPurgeable被設置為true時,inInputShareable的意義還不太理解,API注釋為: If inPurgeable is true, then this field determines whether the bitmap can share a reference to the input data (inputstream, array, etc.) or if it must make a deep copy.慢慢理解吧!
6、outHeight、outWidth:圖像的高度和寬度
7、inScreenDensity:The pixel density of the actual screen that is being used.
8、inTargetDensity:The pixel density of the destination this bitmap will be drawn to.
三、圖片操作
下邊是比較常用的利用bitmap對圖片進行操作的例子:
1、對圖像進行剪切,主要使用Bitmap的createBitmap方法,該方法有6種重載形式,類似:
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {}
source:代表源bitmap
x、y:代表需要進行剪切的起始坐標
width、height:代表需要截取的圖片的寬度和高度
需要注意:x + width must be <= bitmap.width() 並且 y + height must be <= bitmap.height() (否則這就是錯誤提示)
2、對圖像進行縮放,對bitmap進行縮放,可以選擇多種方式:
A、使用Bitmap的帶有Matrix參數的createBitmap方法
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) {}
//例如:
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);//原圖片
Matrix mtrix = new Matrix();
mtrix.postScale(0.25f, 0.25f);
Bitmap targetBitmap = srcBitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), mtrix, true);//目標圖片
B、借助Canvas的scale方法
public void scale(float sx, float sy) {}
不過這是canvas類的方法,從效果上看,bitmap實現了縮放,但本質是canvas的縮放導致的
參數sx代表水平方向的縮放倍數,sy代表豎直方向上的縮放倍數
3、對圖像進行旋轉,也可借助Matrix來實現,例如:
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);//原圖片 Matrix mtrix = new Matrix(); mtrix.postScale(0.25f, 0.25f); mtrix.postRotate(90);//順時針旋轉90度 Bitmap targetBitmap = srcBitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), mtrix, true);//目標圖片
4、借助Matrix來實現對圖像的平移
從上邊的內容中,我們可以發現,Matrix在對bitmap進行旋轉、縮放等過程中起着重要的作用,事實上,在android中,常使用Matrix這個類和Bitmap的createBitmap方法搭配來完成圖片的平移、縮放和旋轉操作。關於Matrix的介紹,網上有非常好的文章可以參考,本文不再詳寫。
作為createBitmap方法的參數,使用之前當然要為Matrix對象賦值以指定需要對圖片采取什么樣的操作,從Matrix.java中,可以看出Matrix對圖片進行操作主要還是依據成員變量mValues的值,即,在調用createBitmap方法之前,需要為Matrix的成員變量mValues賦值,可選方式有兩種:
第一、調用Matrix的set、pre、post方法,如:setScale(float, float)、preTranslate(float, float)和postScale(float, float)等。需要注意的是,set、pre、post方法的執行順序為(該圖片中的內容來源於網絡,謝謝作者):
Matrix matrix = new Matrix();
float[] values ={0.707f,-0.707f,0.0f,0.707f,0.707f,0.0f,0.0f,0.0f,1.0f};
matrix.setValues(values);
Bitmap dstbmp = Bitmap.createBitmap(bmp, 0, 0, 400, 500, matrix, true);
canvas.drawBitmap(dstbmp, 0, 200, null);
在Java代碼中為imageview設置圖片的方式有:
public void setImageResource(int resId) {}
public void setImageDrawable(Drawable drawable) {}
public void setImageBitmap(Bitmap bm) {
setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
}
比較明顯,它們接收的參數類型不同,另外setImageBitmap方法中會先將bitmap對象轉化成drawable對象,並最終調用setImageDrawable方法。
每一次調用setImageBitmap方法都會new一個BitmapDrawable對象,所以,API中也給出了提示:
// if this is used frequently, may handle bitmaps explicitly to reduce the intermediate drawable object
大致意思是,如果需要頻繁調用setImageBitmap方法,最好提供一個中間drawable對象。
bitmap的保存:
//第一個參數:指定格式,第二個參數:壓縮比率,第三個參數:輸出流對象 mBitmap2.compress(Bitmap.CompressFormat.JPEG, 80,輸出流對象);
bitmap的其他操作:
/** 讀取本地資源的圖片 */
public Bitmap readBitMap(int resId) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
InputStream is = getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is, null, opt);
}
/** Drawable 轉 Bitmap */
public static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ?
Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
需要增加一個matrix運用的demo
還需要增加的問題:
1:bitmap和drawable相互轉換之后圖片大小不同的問題
2:bitmap的顯示
3:bitmap的圖片保存
4:bitmap的OOM問題
5:bitmap的讀取等問題
6:imageview的setImageDrawable和setImageBitmap的區別
