1. 程式人生 > >Android中BitmapFactory.Options詳解

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。參看以下原始碼:

  1. try {  
  2.             bm = nativeDecodeByteArray(data, offset, length, opts);  
  3.             if (bm == null && opts != null && opts.inBitmap != null) {  
  4.                 thrownew IllegalArgumentException("Problem decoding into existing bitmap");  
  5.             }  
  6.             setDensityFromOptions(bm, opts);  
  7.         } finally {  
  8.             Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);  
  9.         }  

我們先來分析native方法,以nativeDecodeByteArray方法為例:

可以看到此方法中呼叫了doDecode方法,我們再來看doDecode方法:



通過原始碼可以發現,inDensity,inTargetDensity,inScreenDensity這三個值的主要目的就是確定這個Bitmap的是否會被縮放,如果被縮放,縮放之後的寬高是多少。

再來看setDensityFromOptions這個方法的原始碼:

  1. /** 
  2.      * Set the newly decoded bitmap's density based on the Options. 
  3.      */
  4.     privatestaticvoid setDensityFromOptions(Bitmap outputBitmap, Options opts) {  
  5.         if (outputBitmap == null || opts == nullreturn;  
  6.         finalint density = opts.inDensity;  
  7.         if (density != 0) {  
  8.             outputBitmap.setDensity(density);  
  9.             finalint targetDensity = opts.inTargetDensity;  
  10.             if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {  
  11.                 return;  
  12.             }  
  13.             byte[] np = outputBitmap.getNinePatchChunk();  
  14.             finalboolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);  
  15.             if (opts.inScaled || isNinePatch) {  
  16.                 outputBitmap.setDensity(targetDensity);  
  17.             }  
  18.         } elseif (opts.inBitmap != null) {  
  19.             // bitmap was reused, ensure density is reset
  20.             outputBitmap.setDensity(Bitmap.getDefaultDensity());  
  21.         }  
  22.     }  
從setDensityFromOptions方法中可以得知,會根據Options中的inDensity,inTargetDensity,inScreenDensity三個值和是否被縮放標識inScaled來確定這個Bitmap的mDensity(對應inDensity)。

從以上的分析可以得知,inDensity,inTargetDensity,inScreenDensity這三個值的目的就是為了確定這個Bitmap的寬高和density


--------------------------------------inDensity,inTargetDensity,inScreenDensity----------end-----------------------

inPurgeableinInputShareable

這兩個值一般是一起使用,設定為true時,前者表示空間不夠是否可以被釋放,後者表示是否可以共享引用。這兩個值在Android5.0後被棄用。

inPreferQualityOverSpeed

這個值表示是否在解碼時圖片有更高的品質,僅用於JPEG格式。如果設定為true,則圖片會有更高的品質,但是會解碼速度會很慢。

outWidthoutHeight

表示這個Bitmap的寬和高,一般和inJustDecodeBounds一起使用來獲得Bitmap的寬高,但是不載入到記憶體。