Android中BitmapFactory.Options詳解
原文地址:這裡--->http://blog.csdn.net/haozipi/article/details/47183543?ref=myread
在Android中,BitmapFactory相信大家都很熟悉了,這個類裡面的所有方法都是用來解碼建立一個Bitmap,其中有一個重要的類是Options,此類用於解碼Bitmap時的各種引數控制,那這裡面的各種引數都是什麼含義呢?今天我們就來重點解讀幾個引數。
inJustDecodeBounds:
如果將這個值置為true,那麼在解碼的時候將不會返回bitmap,只會返回這個bitmap的尺寸。這個屬性的目的是,如果你只想知道一個bitmap的尺寸,但又不想將其載入到記憶體時。這是一個非常有用的屬性。
inSampleSize:
這個值是一個int,當它小於1的時候,將會被當做1處理,如果大於1,那麼就會按照比例(1 / inSampleSize)縮小bitmap的寬和高、降低解析度,大於1時這個值將會被處置為2的倍數。例如,width=100,height=100,inSampleSize=2,那麼就會將bitmap處理為,width=50,height=50,寬高降為1 / 2,畫素數降為1 / 4。
inPreferredConfig:
這個值是設定色彩模式,預設值是ARGB_8888,在這個模式下,一個畫素點佔用4bytes空間,一般對透明度不做要求的話,一般採用RGB_565模式,這個模式下一個畫素點佔用2bytes。
inPremultiplied:
這個值和透明度通道有關,預設值是true,如果設定為true,則返回的bitmap的顏色通道上會預先附加上透明度通道。
inDither:
這個值和抖動解碼有關,預設值為false,表示不採用抖動解碼。如果想知道什麼是抖動解碼,請參看我下面:
-------------------------------- Android中的抖動解碼(inDither)-----------Start-------------------------------
在Android中的BitmapFactory.Options中有一個屬性值是inDither,這個值表示是否採用抖動解碼,那什麼叫抖動解碼呢,今天我們就來詳細解說一下。
Bitmap的解碼是根據它所記錄的節點,依照一定演算法,來補充兩個節點之間的資料,可以理解為補充其中畫素點的顏色,那麼在解碼的時候肯定會和當前所採用的顏色模式有關,很直觀的說,採用32位的肯定比16位的顏色要多,自然展現的影象會看起來更好。
如果一張顏色很豐富的圖,用一個位數比較低的顏色模式來解碼的話,那麼一個直觀的感覺就是顏色不夠用,那麼這張圖解出來之後,在一些顏色漸變的區域上就會有一些很明顯的斷裂色帶,這個很好解釋,因為一些豐富的顏色在位數較低的顏色模式下並沒有,那麼只能用相近的填充,可能一大片都沒有,那麼一大片都用這一個顏色填充,就形成了斷裂色帶。
如果採用抖動解碼,那麼就會在這些色帶上採用隨機噪聲色來填充,目的是讓這張圖顯示效果更好,色帶不那麼明顯。
看下面的例子:
很明顯,左邊的更平滑一點,右邊的會有一些色帶,如果不想有這些色帶,那麼就需要採用抖動解碼。
-------------------------------- Android中的抖動解碼(inDither)------------End--------------------------------
inDensity:
表示這個bitmap的畫素密度(對應的是DisplayMetrics中的densityDpi,不是density)。
inTargetDensity:
表示要被畫出來時的目標畫素密度(對應的是DisplayMetrics中的densityDpi,不是density)。
inScreenDensity:
表示實際裝置的畫素密度(對應的是DisplayMetrics中的densityDpi,不是density)。
inScaled:
設定這個Bitmap是否可以被縮放,預設值是true,表示可以被縮放。
ps:inDensity,inTargetDensity,inScreenDensity三個值的具體關係請參看我下面:
--------------------------------------inDensity,inTargetDensity,inScreenDensity---------start-----------------------
這三個屬性值在Bitmap和BitmapFactory中都有不同程度的出現,其中Bitmap中只有mDensity(對應inDensity),BitmapFactory中這三個都有,那麼可以知道這三個值主要是在BitmapFactory中活動,於是我就查看了BitmapFactory中的原始碼,從而知道了這三個值的目的是為了確定這個Bitmap的寬高和density。
下面我們從原始碼角度來分析一下,首先,這個Bitmap通過BitmapFactory創建出來一般經歷兩個方法,一個是解碼的native方法,一個是BitmapFactory中的內部方法setDensityFromOptions。參看以下原始碼:
- try {
- bm = nativeDecodeByteArray(data, offset, length, opts);
- if (bm == null && opts != null && opts.inBitmap != null) {
- thrownew IllegalArgumentException("Problem decoding into existing bitmap");
- }
- setDensityFromOptions(bm, opts);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
- }
我們先來分析native方法,以nativeDecodeByteArray方法為例:
可以看到此方法中呼叫了doDecode方法,我們再來看doDecode方法:
通過原始碼可以發現,inDensity,inTargetDensity,inScreenDensity這三個值的主要目的就是確定這個Bitmap的是否會被縮放,如果被縮放,縮放之後的寬高是多少。
再來看setDensityFromOptions這個方法的原始碼:
- /**
- * Set the newly decoded bitmap's density based on the Options.
- */
- privatestaticvoid setDensityFromOptions(Bitmap outputBitmap, Options opts) {
- if (outputBitmap == null || opts == null) return;
- finalint density = opts.inDensity;
- if (density != 0) {
- outputBitmap.setDensity(density);
- finalint targetDensity = opts.inTargetDensity;
- if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
- return;
- }
- byte[] np = outputBitmap.getNinePatchChunk();
- finalboolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
- if (opts.inScaled || isNinePatch) {
- outputBitmap.setDensity(targetDensity);
- }
- } elseif (opts.inBitmap != null) {
- // bitmap was reused, ensure density is reset
- outputBitmap.setDensity(Bitmap.getDefaultDensity());
- }
- }
從以上的分析可以得知,inDensity,inTargetDensity,inScreenDensity這三個值的目的就是為了確定這個Bitmap的寬高和density。
--------------------------------------inDensity,inTargetDensity,inScreenDensity----------end-----------------------
inPurgeable和inInputShareable:
這兩個值一般是一起使用,設定為true時,前者表示空間不夠是否可以被釋放,後者表示是否可以共享引用。這兩個值在Android5.0後被棄用。
inPreferQualityOverSpeed:
這個值表示是否在解碼時圖片有更高的品質,僅用於JPEG格式。如果設定為true,則圖片會有更高的品質,但是會解碼速度會很慢。
outWidth和outHeight:
表示這個Bitmap的寬和高,一般和inJustDecodeBounds一起使用來獲得Bitmap的寬高,但是不載入到記憶體。