使用inSampleSize对Bitmap进行尺寸缩放,如果inSampleSize大于1,解码器会对原始的bitmap进行子采样图像,减少图像内存占用,例如inSampleSize为4,则采样后的图像宽高为原图像的1/4,而像素值为原图的1/16,内存占用为原图的1/16。而当inSampleSize的值小于等于1,会当作1处理,使用原图像。
调用Glide.into()会执行Downsampler.calculateScaling()对图片的尺寸进行缩放,首先计算出图片与View的宽高比,再根据缩放策略是省内存还是高品质,决定取宽高比的最大值还是最小值,但如果设备的Sdk小于等于23将不支持对wbmp文件进行下采样,不然会通过Integer.highestOneBit()将选取到的比例值四舍五入到最接近的2的幂值得到inSampleSize的值。若此时的缩放策略为省内存,并且inSampleSize值小于由裁剪策略得出的exactScaleFactor值,则会将inSampleSize值再增加一倍。
glide/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java
private static void calculateScaling(
ImageType imageType,
ImageReader imageReader,
DecodeCallbacks decodeCallbacks,
BitmapPool bitmapPool,
DownsampleStrategy downsampleStrategy,
int degreesToRotate,
int sourceWidth,
int sourceHeight,
int targetWidth,
int targetHeight,
BitmapFactory.Options options)
throws IOException {
// We can't downsample source content if we can't determine its dimensions.
if (sourceWidth <= 0 || sourceHeight <= 0) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(
TAG,
"Unable to determine dimensions for: "
+ imageType
+ " with target ["
+ targetWidth
+ "x"
+ targetHeight
+ "]");
}
return;
}
int orientedSourceWidth = sourceWidth;
int orientedSourceHeight = sourceHeight;
//noinspection SuspiciousNameCombination
// 如果我们将图像旋转 +-90 度,我们需要相应地进行下采样,使图像宽度减小到接近目标高度,图像高度减小到接近目标宽度。
if (isRotationRequired(degreesToRotate)) {
orientedSourceWidth = sourceHeight;
orientedSourceHeight = sourceWidth;
}
final float exactScaleFactor =
downsampleStrategy.getScaleFactor(
orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight);
if (exactScaleFactor <= 0f) {
throw new IllegalArgumentException(
"Cannot scale with factor: "
+ exactScaleFactor
+ " from: "
+ downsampleStrategy
+ ", source: ["
+ sourceWidth
+ "x"
+ sourceHeight
+ "]"
+ ", target: ["
+ targetWidth
+ "x"
+ targetHeight
+ "]");
}
SampleSizeRounding rounding =
downsampleStrategy.getSampleSizeRounding(
orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight);
if (rounding == null) {
throw new IllegalArgumentException("Cannot round with null rounding");
}
int outWidth = round(exactScaleFactor * orientedSourceWidth);
int outHeight = round(exactScaleFactor * orientedSourceHeight);
// 1、首先计算出图片与View的宽高比
int widthScaleFactor = orientedSourceWidth / outWidth;
int heightScaleFactor = orientedSourceHeight / outHeight;
// 这对于 CenterOutside 和 CenterInside 来说都不太合适。
// 考虑允许 DownsampleStrategy 选择,或者尝试做一些更复杂的事情,比如选择导致精确匹配的比例因子。
// 2、根据缩放策略是省内存还是高品质,决定取宽高比的最大值还是最小值
int scaleFactor =
rounding == SampleSizeRounding.MEMORY
? Math.max(widthScaleFactor, heightScaleFactor)
: Math.min(widthScaleFactor, heightScaleFactor);
int powerOfTwoSampleSize;
// BitmapFactory does not support downsampling wbmp files on platforms <= M. See b/27305903.
// BitmapFactory 不支持在平台 <= M 上对 wbmp 文件进行下采样。
if (Build.VERSION.SDK_INT <= 23
&& NO_DOWNSAMPLE_PRE_N_MIME_TYPES.contains(options.outMimeType)) {
powerOfTwoSampleSize = 1;
} else {
// 4、通过highestOneBit()把计算的比例四舍五入到最接近2的幂
powerOfTwoSampleSize = Math.max(1, Integer.highestOneBit(scaleFactor));
if (rounding == SampleSizeRounding.MEMORY
// exactScaleFactor 由各个裁剪策略如CenterCrop重写得到
&& powerOfTwoSampleSize < (1.f / exactScaleFactor)) {
// 5、如果缩放策略为省内存,并且计算得出的sampleSize < exactScaleFactor,则sampleSize再增加一倍
powerOfTwoSampleSize = powerOfTwoSampleSize << 1;
}
}
// Here we mimic framework logic for determining how inSampleSize division is rounded on various
// versions of Android. The logic here has been tested on emulators for Android versions 15-26.
// PNG - Always uses floor
// JPEG - Always uses ceiling
// Webp - Prior to N, always uses floor. At and after N, always uses round.
options.inSampleSize = powerOfTwoSampleSize;
..........