分析ImageLoader图片压缩源码分析

310 阅读2分钟

/**

 * Computes sample size for downscaling image size (<b>srcSize</b>) to view size (<b>targetSize</b>). This sample
 * size is used during
 * {@linkplain BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)
 * decoding image} to bitmap.<br />
 * <br />
 * <b>Examples:</b><br />
 * <p/>
 * <pre>
 * srcSize(100x100), targetSize(10x10), powerOf2Scale = true -> sampleSize = 8
 * srcSize(100x100), targetSize(10x10), powerOf2Scale = false -> sampleSize = 10
 *
 * srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE -> sampleSize = 5
 * srcSize(100x100), targetSize(20x40), viewScaleType = CROP       -> sampleSize = 2
 * </pre>
 * <p/>
 * <br />
 * The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded
 * bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16
 * the number of pixels. Any value <= 1 is treated the same as 1.
 *
 * @param srcSize       Original (image) size
 * @param targetSize    Target (view) size
 * @param viewScaleType {@linkplain ViewScaleType Scale type} for placing image in view
 * @param powerOf2Scale <i>true</i> - if sample size be a power of 2 (1, 2, 4, 8, ...)
 * @return Computed sample size
 */
public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType,
		boolean powerOf2Scale) {
	final int srcWidth = srcSize.getWidth();
	final int srcHeight = srcSize.getHeight();
	final int targetWidth = targetSize.getWidth();
	final int targetHeight = targetSize.getHeight();

	int scale = 1;

	switch (viewScaleType) {
		//标准是宽高压缩比例大的
		case FIT_INSIDE:
			if (powerOf2Scale) {
				final int halfWidth = srcWidth / 2;
				final int halfHeight = srcHeight / 2;
				//scale两倍放大,直到压缩后的大小所以目标大小
				while ((halfWidth / scale) > targetWidth || (halfHeight / scale) > targetHeight) { // ||
					scale *= 2;
				}
			} else {
				scale = Math.max(srcWidth / targetWidth, srcHeight / targetHeight); // max
			}
			break;
		case CROP:
		//标准是宽高压缩比例小的
			if (powerOf2Scale) {
				final int halfWidth = srcWidth / 2;
				final int halfHeight = srcHeight / 2;
				while ((halfWidth / scale) > targetWidth && (halfHeight / scale) > targetHeight) { // &&
					scale *= 2;
				}
			} else {
				scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min
			}
			break;
	}

	if (scale < 1) {
		scale = 1;
	}
	//压缩比例因在最大宽高比例内,压缩后的宽高不能超过最大宽高比。
	scale = considerMaxTextureSize(srcWidth, srcHeight, scale, powerOf2Scale);

	return scale;
}

private static int considerMaxTextureSize(int srcWidth, int srcHeight, int scale, boolean powerOf2) {
	final int maxWidth = maxBitmapSize.getWidth();
	final int maxHeight = maxBitmapSize.getHeight();
	while ((srcWidth / scale) > maxWidth || (srcHeight / scale) > maxHeight) {
		if (powerOf2) {
			scale *= 2;
		} else {
			scale++;
		}
	}
	return scale;
}