Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 位圖(一) BitmapFactory類

Android 位圖(一) BitmapFactory類

編輯:關於Android編程

在使用Bitmap(位圖)中,我們總是會與BitmapFactory類打交道。今天就來看看BitmapFactory的廬山真面目。

首先依舊是看看官網的定義:

Creates Bitmap objects from various sources, including files, streams, and byte-arrays. 

翻譯:BitmapFactory 用於從各種資源、文件、流和字節數組中創建Bitmap(位圖)對象。

簡而言之,就是說使用BitmapFactory類就可以創建Bitmap(位圖)了。(當然,創建Bitmap(位圖)還有其他方式,下篇文章會講解)接下來,我們就看看系統提供的BitmapFactory類提供的用於創建Bitmap(位圖)的方法。BitmapFactory類是一個工具類,提供大量方法,這些方法可用於從不同的數據源解析、創建Bitmap(位圖)。

一.BitmapFactory 類創建Bitmap(位圖)的方法說明。

 

1. public static Bitmap decodeByteArray (byte[] data, int offset, int length, BitmapFactory.Options opts)
參數
data 	壓縮圖像數據的字節數組
offset 	圖像數據偏移量,用於解碼器開始從哪兒解析.
length 	字節數,以偏移量開始,去解析
opts 	可以為空,控制采樣率和實付圖像完全被解碼的選項,或者僅僅返回大小
返回值
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空,或者 如果選項不是空,如果選項要求僅僅返回大小(opts.outWidth and opts.outHeight)。
從指定的字節數組中解碼一個不可變的位圖。

 

 

2. public static Bitmap decodeByteArray (byte[] data, int offset, int length)
參數
data 	壓縮圖像數據的字節數組
offset  圖像數據偏移量,用於解碼器開始從哪兒解析.
length 	字節數,以偏移量開始,去解析
返回值 
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空
從指定的字節數組中解碼一個不可變的位圖。

 

3. public static Bitmap decodeFile (String pathName)
參數
pathName 	解碼文件的全路徑名
返回值
	返回結果是解碼的位圖,或者如果不能解碼則返回空。
從文件中解碼生成一個位圖。如果支付的文件名為空,或者不能解碼出一個位圖,方法將返回空。

4. public static Bitmap decodeFile (String pathName, BitmapFactory.Options opts)
參數
pathName 	解碼文件的全路徑名
opts 	        可以為空,控制采樣率和實付圖像完全被解碼的選項,或者僅僅返回大小
Returns
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空,或者 如果選項不是空,如果選項要求僅僅返回大小(opts.outWidth and opts.outHeight)。
從文件中解碼生成一個位圖。如果支付的文件名為空,或者不能解碼出一個位圖,方法將返回空。

5. public static Bitmap decodeFileDescriptor (FileDescriptor fd)
參數
fd 	包含解碼位圖數據的文件路徑
返回值
   返回解碼的位圖或者空。
從文件路徑中解碼位圖。如果不能解碼問題返回空。當返回的時候,描述符的位置不會改變,因此可以再次使用描述符。

6. public static Bitmap decodeFileDescriptor (FileDescriptor fd, Rect outPadding, BitmapFactory.Options opts)
參數
fd 	        包含解碼位圖數據的文件路徑
outPadding 	如果不為空,返回矩形的內邊距如果位圖存在,否則設置內邊距為(-1,-1,-1,-1).如果沒有位圖返回空,內邊距不改變
opts 	        可以為空,控制采樣率和實付圖像完全被解碼的選項,或者僅僅返回大小
返回值
    返回解碼的位圖或者空。 
從文件路徑解碼位圖。如果不能解碼問題返回空。當返回的時候,描述符的位置不會改變,因此可以再次使用描述符。

7. public static Bitmap decodeResource (Resources res, int id, BitmapFactory.Options opts)
參數
res 	包含圖像數據的資源對象
id 	圖像數據的資源的id
opts 	可以為空,控制采樣率和實付圖像完全被解碼的選項,或者僅僅返回大小
返回值
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空,或者 如果選項不是空,如果選項要求僅僅返回大小(opts.outWidth and opts.outHeight)。
打開給的資源獲取位圖,與decodeResourceStream(Resources, TypedValue, InputStream, Rect, BitmapFactory.Options)同義。

8. public static Bitmap decodeResourceStream (Resources res, TypedValue value, InputStream is, Rect pad, BitmapFactory.Options opts)
從輸入流中解碼一個新位圖。輸入了獲得資源,我們可以縮放位圖。

9. public static Bitmap decodeResource (Resources res, int id)
參數
res 	    包含圖像數據的資源對象
id 	    圖像數據的資源的id
返回值
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空
從輸入流中解碼位圖。與decodeResource(Resources, int, android.graphics.BitmapFactory.Options)當Options是空時同義,

10. public static Bitmap decodeResource (Resources res, int id, BitmapFactory.Options opts)
參數
res 	包含圖像數據的資源對象
id 	圖像數據的資源的id
opts 	可以為空,控制采樣率和實付圖像完全被解碼的選項,或者僅僅返回大小
返回值
   返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空,或者 如果選項不是空,如果選項要求僅僅返回大小(opts.outWidth and opts.outHeight)。
從資源中解碼一個位圖。與decodeResourceStream(Resources, TypedValue, InputStream, Rect, BitmapFactory.Options)同義.

11. public static Bitmap decodeStream (InputStream is, Rect outPadding, BitmapFactory.Options opts)
參數
is 	        持有原始數據用於解碼位圖的輸入流
outPadding 	如果不為空,返回矩形的內邊距如果位圖存在,否則設置內邊距為(-1,-1,-1,-1).如果沒有位圖返回空,內邊距不改變
opts 	        可以為空,控制采樣率和實付圖像完全被解碼的選項,或者僅僅返回大小
Returns
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空,或者 如果選項不是空,如果選項要求僅僅返回大小(opts.outWidth and opts.outHeight)。
從輸入流中解碼一個位圖。如果輸入了為空,或者不能解碼位圖,方法返回空。流的位置覺得解碼數據從哪兒讀取。

12. public static Bitmap decodeStream (InputStream is)
Decode an input stream into a bitmap. If the input stream is null, or cannot be used to decode a bitmap, the function returns null. The stream's position will be where ever it was after the encoded data was read.
參數
is 	持有原始數據用於解碼位圖的輸入流
返回值
    返回解碼後的位圖,或者如果圖像數據不能被解碼返回為空
從輸入流中解碼一個位圖。如果輸入了為空,或者不能解碼位圖,方法返回空。流的位置覺得解碼數據從哪兒讀取。

以上就是BitmapFactory類創建Bitmap(位圖)的方法匯總。上面列舉的方法中,有一個參數比較重要就是BitmapFactory.Options類,下面,我們看看BitmapFactory.Options類的說明以及使用。

二.BitmapFactory.Options說明以及使用。

還是依舊看官方的定義:

 

Create a default Options object, which if left unchanged will give the same result from the decoder as if null were passed. 
翻譯:創建默認選項對象,如果保持不變將從解碼器得到相同的結果,如果是空則通過。

 

換句話說,就是設置這個值,可以更好的控制、顯示、使用Bitmap(位圖)。我們在實際開發中,可以靈活的使用該值,就可能會減少OOM的發生。是不是很高興很激動呢!大笑。下面,我們就介紹幾個BitmapFactory.Options類比較重要的屬性值。

2.1 inJustDecodeBounds。

先看看定義:

boolean inJustDecodeBounds
If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
翻譯:如果設置為真,解碼將返回空(沒有位圖),但是輸出的字段依然被設置,允許調用者查詢Bitmap(位圖)而不用為其像素分配內存。

 

也就是說,我們想要獲取位圖的寬和高時,可以設置inJustDecodeBounds為'true',那麼此時並不會返回一個Bitmap(位圖),並且位圖不會占用內存,但是會返回位圖的寬和高。options.outWidth 和 options.outHeight就是我們想要的寬和高。具體代碼示例如下,(是Android官方給的計算代碼)

 

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

 

PS:BitmapFactory獲取圖片的寬、高信息和圖片的位置信息以及程序運行的設備有關,比如同一張圖片放在不同的drawable目錄下,或者程序運行在不同屏幕密碼的設備上著都可能導致BitmapFactory獲取到不同的結果,之所以會這樣,這和Android的資源加載機制有關,相信讀者平時裡肯定有所體會。

除了設置inJustDecodeBounds,我們可以設置inSampleSize屬性,達到合理使用內存。

2.2inSampleSize。

采樣率,設置它,可以縮放圖片。官方建議取值為2的冪數,比如1、2、4、8、16等。例如,當設置inSampleSize=1時,采樣後的圖片大小為圖片的原始大小;inSampleSize大於1時,比如2,那麼采樣後的圖片寬/高均為原圖大小的1/2,總像素為原圖的1/4,其占用內存也為原圖的1/4,例如一張1024*1024的像素圖片,假如采用ARGB_8888格式存儲,它占用的內存大小大約是=1024*1024*4=4MB。如果inSampleSize=2,那麼采樣後的圖片其內存占用是512*512*4=1MB。如果inSampleSize小於1,則按1處理;其他任何值將四捨五入到最接近2的冪數!我們可以動態計算inSampleSize的值,如下所示,

(1).計算inSampleSize的值,(是Android官方給的計算代碼)

 

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
上述代碼可以看出,計算的結果肯定是2的冪數。

 

接下來,我們結合inJustDecodeBounds和inSampleSize這兩個屬性,看看如何共同使用,示例代碼如下:(是Android官方給的計算代碼)

 

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
首先設置inJustDecodeBounds為‘true’,計算出位圖的寬、高,然後在計算inSampleSize的值,再次設置nJustDecodeBounds為‘false’,最後調用BitmapFactory.decodeResource()方法解碼位圖。是不是比較簡單呢!
例如加載一張圖片至ImageView,大小為100*100,代碼如下所示:(是Android官方給的計算代碼)
mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

上述幾段代碼,均來自Android官方的文檔。推薦大家有時間,可以仔細看看官方文檔!

 

下面,我們就使用BitmapFactory來創建Bitmap(位圖)。

三. BitmapFactory來創建Bitmap(位圖),示例代碼如下,

(1).Bitmap工具類。

 

/**
 * Bitmap工具類
 */
public class BitmapUtils {

	/**
	 * @param res
	 * @param id
	 * @param opts
	 * @return
	 */
	public static Bitmap decodeResource(Resources res, int id,
			BitmapFactory.Options opts) {
		return BitmapFactory.decodeResource(res, id, opts);
	}

	/**
	 * @param res
	 * @param id
	 * @return
	 */
	public static Bitmap decodeResource(Resources res, int id) {
		return BitmapFactory.decodeResource(res, id);
	}

	/**
	 * @param pathName
	 * @return
	 */
	public static Bitmap decodeFile(String pathName) {
		return BitmapFactory.decodeFile(pathName);
	}

	/**
	 * @param pathName
	 * @param opts
	 * @return
	 */
	public static Bitmap decodeFile(String pathName, BitmapFactory.Options opts) {
		return BitmapFactory.decodeFile(pathName, opts);
	}

	/**
	 * @param is
	 * @return
	 */
	public static Bitmap decodeStream(InputStream is) {
		return BitmapFactory.decodeStream(is);
	}

}

(2). 生成Bitmap(位圖),

 

 

 //從drawable中獲取
	bitmap=BitmapUtils.decodeResource(getResources(), R.drawable.iv_mt_ic);
	//從assets中獲取
	try {
			InputStream is=this.getAssets().open("iv_dzdp_iv.png");
			 bitmap=BitmapUtils.decodeStream(is);
	} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	}
	//從sdcard中獲取
	String path="/sdcard/img.jpg";
	bitmap=BitmapUtils.decodeFile(path);

 

 

上述代碼,列舉了幾種使用BitmapFactory創建Bitmap(位圖)的方法。

三. 總結。

實際開發中,使用BitmapFactory創建Bitmap(位圖)還是比較多的,結合BitmapFactory.Options類,可以更方便、快捷!本篇文章介紹BitmapFactory就到此!希望對你有所幫忙!如有描述錯誤,請指出!

 



 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved