Android - bitmap簡單總結


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被回收。
5inInputShareable:當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類的setValues(float[] values)方法,如:
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的區別

 


免責聲明!

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



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