package com.iwedia.gui.imagecache;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import android.util.LruCache;
import java.io.File;
/**
* Implementation of LruMemoryCache. Caching Bitmap in memory.
*
* @author Milos Milanovic
*/
public class ImageMemCache {
/** Activity instance */
private Activity activity = null;
/** LruCache Instance */
private LruCache<String, Bitmap> mCache = null;
public ImageMemCache(Activity activity) {
this.activity = activity;
initMem();
}
/** Configuration of Memory size for Caching and initialization. */
private void initMem() {
// Get current memory size
final int memClass = ((ActivityManager) activity
.getApplicationContext().getSystemService(
Context.ACTIVITY_SERVICE)).getMemoryClass();
// Set the size of cached memory
final int mCacheSize = 1024 * 1024 * memClass / 8;
// Init LruCache
mCache = new LruCache<String, Bitmap>(mCacheSize);
}
/**
* Add Bitmap to LruCache (Memory).
*
* @param key
* resourceId
* @param rawBitmap
* Bitmap
*/
public synchronized void addBitmapToMemoryCache(String key, Bitmap rawBitmap) {
if (getBitmapFromMemCache(key) == null) {
Bitmap bitmap = createReflectedImage(rawBitmap);
mCache.put(key, bitmap);
}
}
/**
* Add Bitmap to LruCache (Memory).
*
* @param key
* resourceId
* @param rawBitmap
* Bitmap
*/
public synchronized void addBitmapToMemoryCacheWithoutReflection(
String key, Bitmap rawBitmap) {
if (getBitmapFromMemCache(key) == null) {
mCache.put(key, rawBitmap);
}
}
/**
* Add Images to Memory from resource.
*
* @param imageIds
* Array of resourceIds
*/
public void addImagesToMemory(Integer[] imageIds) {
for (Integer id : imageIds) {
final Bitmap bitmap = BitmapFactory.decodeResource(
activity.getResources(), id);
if (bitmap != null) {
addBitmapToMemoryCache(String.valueOf(id), bitmap);
}
}
}
/**
* Return bitmap from memory.
*/
private Bitmap getBitmapFromMemCache(String key) {
return (Bitmap) mCache.get(key);
}
/**
* Get bitmap from memory or get from resource and put it in memory.
*/
public Bitmap loadBitmapFromResource(int resId) {
final String imageKey = String.valueOf(resId);
Bitmap bitmap = getBitmapFromMemCache(imageKey);
if (bitmap != null) {
return bitmap;
} else {
Bitmap rawBitmap = BitmapFactory.decodeResource(
activity.getResources(), resId);
if (rawBitmap != null) {
bitmap = createReflectedImage(rawBitmap);
rawBitmap.recycle();
}
BitmapWorkerTask task = new BitmapWorkerTask(this);
task.execute(resId, bitmap);
return bitmap;
}
}
/**
* Get bitmap from memory or get from disk and put it in memory.
*/
public Bitmap loadBitmapFromDisk(String path) {
File imgPath = new File(path);
if (imgPath.exists()) {
Bitmap bitmap = getBitmapFromMemCache(path);
if (bitmap != null) {
return bitmap;
} else {
Bitmap rawBitmap = BitmapFactory.decodeFile(path);
addBitmapToMemoryCacheWithoutReflection(
imgPath.getAbsolutePath(), rawBitmap);
return rawBitmap;
}
} else {
return null;
}
}
/** Image reflection */
public Bitmap createReflectedImage(Bitmap originalImage) {
// The gap we want between the reflection and the original image
int reflectionGap = 0;
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matrix applied to it.
// We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
3 * height / 4, width, height / 4, matrix, false);
// Create a new bitmap with same width but taller to fit
// reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(originalImage, 0, 0, null);
// Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafaultPaint);
// Draw in the reflection
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the
// reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
}
}