/* * Copyright (C) 2016 Peng fei Pan <sky@xiaopan.me> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.xiaopan.sketch.state; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import me.xiaopan.sketch.Configuration; import me.xiaopan.sketch.Sketch; import me.xiaopan.sketch.SketchMonitor; import me.xiaopan.sketch.cache.BitmapPool; import me.xiaopan.sketch.cache.BitmapPoolUtils; import me.xiaopan.sketch.cache.MemoryCache; import me.xiaopan.sketch.drawable.ImageAttrs; import me.xiaopan.sketch.drawable.RefBitmap; import me.xiaopan.sketch.drawable.RefBitmapDrawable; import me.xiaopan.sketch.drawable.ShapeBitmapDrawable; import me.xiaopan.sketch.process.ImageProcessor; import me.xiaopan.sketch.process.ResizeImageProcessor; import me.xiaopan.sketch.request.DisplayOptions; import me.xiaopan.sketch.request.ImageViewInterface; import me.xiaopan.sketch.request.Resize; import me.xiaopan.sketch.request.ShapeSize; import me.xiaopan.sketch.request.UriScheme; import me.xiaopan.sketch.shaper.ImageShaper; import me.xiaopan.sketch.util.SketchUtils; /** * 可以利用Options中配置的ImageProcessor和resize修改原图片,同样支持ShapeSize和ImageShaper */ @SuppressWarnings("unused") public class MakerStateImage implements StateImage { private int resId; public MakerStateImage(int resId) { this.resId = resId; } public int getResId() { return resId; } @Override public Drawable getDrawable(Context context, ImageViewInterface imageViewInterface, DisplayOptions displayOptions) { Drawable drawable = makeDrawable(Sketch.with(context), displayOptions); ShapeSize shapeSize = displayOptions.getShapeSize(); ImageShaper imageShaper = displayOptions.getImageShaper(); if ((shapeSize != null || imageShaper != null) && drawable != null && drawable instanceof BitmapDrawable) { drawable = new ShapeBitmapDrawable(context, (BitmapDrawable) drawable, shapeSize, imageShaper); } return drawable; } private Drawable makeDrawable(Sketch sketch, DisplayOptions options) { Configuration configuration = sketch.getConfiguration(); ImageProcessor processor = options.getImageProcessor(); Resize resize = options.getResize(); BitmapPool bitmapPool = configuration.getBitmapPool(); // 不需要处理的时候直接取出图片返回 if (processor == null && resize == null) { return configuration.getContext().getResources().getDrawable(resId); } // 从内存缓存中取 String memoryCacheKey = SketchUtils.makeStateImageMemoryCacheKey(String.valueOf(resId), options); MemoryCache memoryCache = configuration.getMemoryCache(); RefBitmap cachedRefBitmap = memoryCache.get(memoryCacheKey); if (cachedRefBitmap != null) { if (cachedRefBitmap.isRecycled()) { memoryCache.remove(memoryCacheKey); } else { return new RefBitmapDrawable(cachedRefBitmap); } } // 读取图片 Bitmap bitmap; boolean allowRecycle = false; boolean tempLowQualityImage = configuration.isGlobalLowQualityImage() || options.isLowQualityImage(); //noinspection deprecation Drawable drawable = configuration.getContext().getResources().getDrawable(resId); if (drawable != null && drawable instanceof BitmapDrawable) { bitmap = ((BitmapDrawable) drawable).getBitmap(); } else { bitmap = SketchUtils.drawableToBitmap(drawable, tempLowQualityImage, bitmapPool); allowRecycle = true; } if (bitmap == null || bitmap.isRecycled()) { return null; } // 处理图片 //noinspection ConstantConditions if (processor == null && resize != null) { processor = sketch.getConfiguration().getResizeImageProcessor(); if (processor == null) { processor = new ResizeImageProcessor(); } } Bitmap newBitmap; try { newBitmap = processor.process(sketch, bitmap, resize, options.isForceUseResize(), tempLowQualityImage); } catch (OutOfMemoryError e) { e.printStackTrace(); SketchMonitor sketchMonitor = sketch.getConfiguration().getMonitor(); sketchMonitor.onProcessImageError(e, UriScheme.DRAWABLE.createUri(String.valueOf(resId)), processor); if (allowRecycle) { BitmapPoolUtils.freeBitmapToPool(bitmap, bitmapPool); } return null; } // bitmap变化了,说明创建了一张全新的图片,那么就要回收掉旧的图片 if (newBitmap != bitmap) { if (allowRecycle) { BitmapPoolUtils.freeBitmapToPool(bitmap, bitmapPool); } // 新图片不能用说你处理部分出现异常了,直接返回null即可 if (newBitmap == null || newBitmap.isRecycled()) { return null; } bitmap = newBitmap; allowRecycle = true; } // 允许回收说明是创建了一张新的图片,不能回收说明还是从res中获取的BitmapDrawable可以直接使用 if (allowRecycle) { BitmapFactory.Options boundsOptions = new BitmapFactory.Options(); boundsOptions.inJustDecodeBounds = true; BitmapFactory.decodeResource(configuration.getContext().getResources(), resId, boundsOptions); String uri = UriScheme.DRAWABLE.createUri(String.valueOf(resId)); ImageAttrs imageAttrs = new ImageAttrs(boundsOptions.outMimeType, boundsOptions.outWidth, boundsOptions.outHeight, 0); RefBitmap newRefBitmap = new RefBitmap(bitmap, memoryCacheKey, uri, imageAttrs, bitmapPool); memoryCache.put(memoryCacheKey, newRefBitmap); return new RefBitmapDrawable(newRefBitmap); } else { return drawable; } } }