1. 程式人生 > >Glide探究一 如何計算載入後的圖片尺寸?

Glide探究一 如何計算載入後的圖片尺寸?

Glide探究一 如何計算載入後的圖片尺寸?

一、疑問

  • 呼叫RequestBuilder into(@NonNull ImageView view),載入後的圖片尺寸是多少?
  • 呼叫RequestBuilder into(@NonNull Y target)
    ,載入後的圖片尺寸是多少?
  • 呼叫RequestOptions override(int width, int height),載入後的圖片尺寸是多少?

二、請求尺寸

無論使用何種方式載入圖片,Glide首先計算request請求尺寸。請求尺寸可以在2個地方進行設定。

  • Target
  • RequestOptions

通過RequestBuilder into(@NonNull ImageView view),實質上是通過Target實現的,確切地說是BitmapImageViewTarget或者DrawableImageViewTargetTarget

介面中提供了一個常量SIZE_ORIGINAL用於將請求尺寸設定為圖片尺寸。

int SIZE_ORIGINAL = Integer.MIN_VALUE;

其次,可以在RequestOptions中通過override(int width, int height)覆蓋Target地請求尺寸。

三、三種尺寸

  • request請求尺寸(在Target或者RequestOptions中設定的尺寸)
  • source源圖片尺寸(圖片自身尺寸)
  • target目標尺寸(載入後的圖片尺寸)

上一部分中,我們已經知道如何設定Gliderequest請求尺寸,並且圖片的自身的source

源尺寸是確定的。如何通過requestsource兩種尺寸計算出最終的target大小?答案是DownsampleStrategy

四、DownsampleStrategy

DownsampleStrategy定義了2個抽象方法

public abstract float getScaleFactor(
    int sourceWidth, int sourceHeight, 
    int requestedWidth, int requestedHeight);

public abstract SampleSizeRounding getSampleSizeRounding(
    int sourceWidth, int sourceHeight,
    int requestedWidth, int requestedHeight);

getScaleFactor根據sourcerequest大小計算出縮放比例來確定target尺寸。

getSampleSizeRounding用於計算inSampleSize的數值,SampleSizeRounding有2個列舉值。

  • MEMORY記憶體優先,增加inSampleSize值,保證較小的記憶體使用。
  • QUALITY質量優先,降低inSampleSize值,保證較高的圖片質量。

DownsampleStrategy的定義可以看出,Glide載入後的圖片保持了原始比例。

五、BitmapFactory.Options

通過DownsmapleStrategygetScaleFactor方法,計算出scaleFactor縮放比例。從而計算出最終的target尺寸。

targetWidth = sourceWidth * scaleFactor; 
targetHeight = sourceHeight * scaleFactor; 

接下來通過BitmapFactory載入圖片即可。與載入圖片相關的幾個重要引數

public boolean inJustDecodeBounds; // 僅解碼圖片尺寸,並不載入圖片

public Bitmap inBitmap; // 複用已有的Bitmap,Glide總是優先使用inBitmap複用圖片

public int inSampleSize; // 取樣大小,必須是2的指數,<= 1,2,4,8,16,……

public boolean inScaled; // 縮放,結合inTargetDensity和inDensity確定最終圖片大小
public int inTargetDensity; // 目標Density
public int inDensity; // 源Density

BitmapFactory.Options幾個引數對載入後Bitmap尺寸的影響。

// inScaled = false,inTargetDensity = inDensity = 0時
// 取樣值越大,得到的Bitmap尺寸越小
bitmap.width = sourceWidth / inSampleSize; 
bitmap.height = sourceHeight / inSampleSize; 
// 同時對圖片進行縮放
bitmap.width = sourceWidth / inSampleSize * inTargetDensity / inDensity; 
bitmap.height = sourceHeight / inSampleSize * inTargetDensity / inDensity; 

六、Downsampler

Downsampler完成了圖片的載入過程。

public Resource<Bitmap> decode(
    InputStream is, 
    int requestedWidth, int requestedHeight,
    Options options, 
    DecodeCallbacks callbacks) throws IOException;  // 注意request大小
private Bitmap decodeFromWrappedStreams(
    InputStream is,
    BitmapFactory.Options options, 
    DownsampleStrategy downsampleStrategy,
    DecodeFormat decodeFormat, boolean isHardwareConfigAllowed, 
    int requestedWidth, int requestedHeight, 
    boolean fixBitmapToRequestedDimensions, 
    DecodeCallbacks callbacks) throws IOException; // 出現了downsampleStrategy
private static void calculateScaling(
      ImageType imageType,
      InputStream is,
      DecodeCallbacks decodeCallbacks,
      BitmapPool bitmapPool,
      DownsampleStrategy downsampleStrategy,
      int degreesToRotate,
      int sourceWidth,
      int sourceHeight,
      int targetWidth,
      int targetHeight,
      BitmapFactory.Options options) throws IOException; // target大小已經確定

七、RequestOptions

RequestOptions中設定request尺寸及DownsampleStrategy

public RequestOptions override(int width, int height); 

public RequestOptions downsample(@NonNull DownsampleStrategy strategy); 

八、總結

  • BitmapFactory.Options的4個引數inSampleSizeinScaledinTargetDensityinDensity共同決定了載入後的bitmap大小;
  • DownsampleStrategy計算requestsource尺寸的縮放比例,進而計算出BitmapFactory.Options的最終引數;
  • RequestOptions中設定request大小及DownsampleStrategy
  • Downsampler完成了所以計算工作,並完成載入圖片的工作;