Glide探究一 如何计算加载后的图片尺寸?

版权声明:个人原创,欢迎转载。 https://blog.csdn.net/chuyangchangxi/article/details/83990064

一、疑问

  • 调用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完成了所以计算工作,并完成加载图片的工作;

猜你喜欢

转载自blog.csdn.net/chuyangchangxi/article/details/83990064
今日推荐