package com.mrwang.imageframe; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.support.annotation.NonNull; import android.support.annotation.RawRes; import static android.graphics.BitmapFactory.decodeFile; import static android.graphics.BitmapFactory.decodeStream; /** * User: chengwangyong([email protected]) * Date: 2017/3/16 * Time: 下午5:13 */ public class BitmapLoadUtils { /** * 两种模式 * 一种启用缓存 loop后下一次不读取磁盘 但是内存抖动 内存占用大 空间换磁盘 cpu性能 内存抖动 * 一种不启用缓存, loop会读取磁盘,占用磁盘资源,但是内存永远是一张图片的内存 内存不抖动 * */ public static BitmapDrawable decodeSampledBitmapFromFile(String filename, int reqWidth, int reqHeight, ImageCache cache, boolean isOpenLruCache) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; decodeFile(filename, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); BitmapDrawable bitmapFromCache; if (isOpenLruCache) { bitmapFromCache = cache.getBitmapFromCache(filename); if (bitmapFromCache == null) { // if (Utils.hasHoneycomb()) { bitmapFromCache = readBitmapFromFile(filename, cache, options); cache.addBitmap(filename, bitmapFromCache); } } else { bitmapFromCache = readBitmapFromFile(filename, cache, options); } return bitmapFromCache; } @NonNull private static BitmapDrawable readBitmapFromFile(String filename, ImageCache cache, BitmapFactory.Options options) { BitmapDrawable bitmapFromCache; addInBitmapOptions(options, cache); // } // If we're running on Honeycomb or newer, try to use inBitmap. options.inJustDecodeBounds = false; bitmapFromCache = new BitmapDrawable(BitmapFactory.decodeFile(filename, options)); return bitmapFromCache; } static BitmapDrawable decodeSampledBitmapFromRes(Resources resources, @RawRes int resId, int reqWidth, int reqHeight, ImageCache cache, boolean isOpenLruCache) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; decodeStream(resources.openRawResource(resId), null, options); options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // String resourceName = resources.getResourceName(resId); // if (Utils.hasHoneycomb()) { BitmapDrawable bitmapFromCache; if (isOpenLruCache) { String resourceName = resources.getResourceName(resId); bitmapFromCache = cache.getBitmapFromCache(resourceName); if (bitmapFromCache == null) { // if (Utils.hasHoneycomb()) { bitmapFromCache = readBitmapFromRes(resources, resId, cache, options); cache.addBitmap(resourceName, bitmapFromCache); } } else { bitmapFromCache = readBitmapFromRes(resources, resId, cache, options); } return bitmapFromCache; } @NonNull private static BitmapDrawable readBitmapFromRes(Resources resources, @RawRes int resId, ImageCache cache, BitmapFactory.Options options) { addInBitmapOptions(options, cache); // } // If we're running on Honeycomb or newer, try to use inBitmap. options.inJustDecodeBounds = false; return new BitmapDrawable(resources, decodeStream(resources.openRawResource(resId), null, options)); } private static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // 原始图片的宽高 if (reqHeight == 0 || reqWidth == 0) { return 1; } final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // 在保证解析出的bitmap宽高分别大于目标尺寸宽高的前提下,取可能的inSampleSize的最大值 // The maximum value of the inSampleSize can be obtained on the premise of ensuring that the // width and height of the bitmap are larger than the target size while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } private static void addInBitmapOptions(BitmapFactory.Options options, ImageCache cache) { // inBitmap only works with mutable bitmaps, so force the decoder to // return mutable bitmaps. options.inMutable = true; if (cache != null) { // Try to find a bitmap to use for inBitmap. Bitmap inBitmap = cache.getBitmapFromReusableSet(options); if (inBitmap != null) { // If a suitable bitmap has been found, set it as the value of // inBitmap. options.inBitmap = inBitmap; } } } }