package com.crossbow.volley;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.support.v4.graphics.BitmapCompat;
import com.android.volley.VolleyLog;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
/**
*/
public class BitmapScrapHeap {
private static BitmapScrapHeap bitmapScrapHeap;
private static final int UNUSED_BITMAP_COUNT = 50;
private Set<WeakReference<Bitmap>> unusedBitmaps;
public static BitmapScrapHeap get() {
if(bitmapScrapHeap == null) {
bitmapScrapHeap = new BitmapScrapHeap();
}
return bitmapScrapHeap;
}
private BitmapScrapHeap() {
unusedBitmaps = Collections.newSetFromMap(new LinkedHashMap<WeakReference<Bitmap>, Boolean>(UNUSED_BITMAP_COUNT) {
protected boolean removeEldestEntry(Entry<WeakReference<Bitmap>, Boolean> eldest) {
boolean shouldRemove = size() > UNUSED_BITMAP_COUNT;
if (shouldRemove) {
VolleyLog.d("Pruning unused size = " + size());
Bitmap toBeScrapped = eldest.getKey().get();
if(toBeScrapped != null) {
toBeScrapped.recycle();
}
}
return shouldRemove;
}
});
}
public Bitmap getBitmapToFill(BitmapFactory.Options options) {
synchronized (unusedBitmaps) {
Iterator<WeakReference<Bitmap>> iterator = unusedBitmaps.iterator();
while (iterator.hasNext()) {
Bitmap bitmap = iterator.next().get();
if(bitmap != null) {
if(bitmap.isMutable() && canUseForInBitmap(bitmap, options)) {
iterator.remove();
return bitmap;
}
}
else {
iterator.remove();
}
}
}
return null;
}
public void storeForReUse(Bitmap bitmap) {
synchronized(unusedBitmaps) {
if(bitmapCanBeReused(bitmap)) {
unusedBitmaps.add(new WeakReference<Bitmap>(bitmap));
}
}
}
private static boolean bitmapCanBeReused(Bitmap bitmap) {
return bitmap != null && !bitmap.isRecycled() && bitmap.isMutable();
}
private static boolean canUseForInBitmap(Bitmap candidate, BitmapFactory.Options targetOptions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if(targetOptions.inSampleSize == 0) {
final int width = targetOptions.outWidth;
final int height = targetOptions.outHeight;
final int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
return byteCount <= BitmapCompat.getAllocationByteCount(candidate);
}
final int width = targetOptions.outWidth / targetOptions.inSampleSize;
final int height = targetOptions.outHeight / targetOptions.inSampleSize;
final int byteCount = width * height * getBytesPerPixel(candidate.getConfig());
return byteCount <= BitmapCompat.getAllocationByteCount(candidate);
}
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return candidate.getWidth() == targetOptions.outWidth && candidate.getHeight() == targetOptions.outHeight && targetOptions.inSampleSize == 1;
}
else {
return false;
}
}
private static int getBytesPerPixel(Bitmap.Config config) {
if (config == Bitmap.Config.ARGB_8888) {
return 4;
}
else if (config == Bitmap.Config.RGB_565) {
return 2;
}
else if (config == Bitmap.Config.ARGB_4444) {
return 2;
}
else if (config == Bitmap.Config.ALPHA_8) {
return 1;
}
return 1;
}
}