Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added LruCache, which is dependent on android-support-v4.jar. #7

Merged
merged 1 commit into from Mar 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 8 additions & 5 deletions res/layout/main.xml
Expand Up @@ -4,12 +4,15 @@
xmlns:ctc="http://schemas.android.com/apk/res/com.ctc.android.widget"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:layout_height="fill_parent">

<com.ctc.android.widget.ImageMap
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/usamap"
ctc:map="usamap"/>
android:layout_height="fill_parent"
ctc:map="usamap"
ctc:maxSizeFactor="1.5"
ctc:scaleFromOriginal="true"
ctc:fitImageToScreen="true"/>

</LinearLayout>
71 changes: 71 additions & 0 deletions src/com/ctc/android/widget/BitmapHelper.java
@@ -0,0 +1,71 @@
package com.ctc.android.widget;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.Log;

/**
* This class helps caching images for faster loading on second activity open.
* May also be used at startup to load all images into memory.
* Created by fess on 2/6/14.
*
* The implementation is taken from the official manual:
* @link http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
*
* TODO: implement asynchronous image loading.
* TODO: configurable cache size.
*
*/
public class BitmapHelper
{
private LruCache<String, Bitmap> mMemoryCache;

public static BitmapHelper instance;

public static BitmapHelper getInstance()
{
if (null == instance)
{
instance = new BitmapHelper();
}
return instance;
}

private BitmapHelper()
{
//trying to implement image caching
// Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an
// int in its constructor.
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

// Use 1/2nd of the available memory for this memory cache.
final int cacheSize = maxMemory / 2;

mMemoryCache = new LruCache<String, Bitmap>(cacheSize)
{
@Override
protected int sizeOf(String key, Bitmap bitmap)
{
// The cache size will be measured in kilobytes rather than
// number of items.
return bitmap.getRowBytes()*bitmap.getHeight() / 1024;
}
};
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap)
{
if (getBitmapFromMemCache(key) == null)
{
Log.e("Bitmap Helper", "Putting bitmap to cache for key: " + key);
mMemoryCache.put(key, bitmap);
}
}

public Bitmap getBitmapFromMemCache(String key)
{
Log.e("Bitmap Helper", "Loading bitmap from cache for key: " + key);
return mMemoryCache.get(key);
}
}
53 changes: 48 additions & 5 deletions src/com/ctc/android/widget/ImageMap.java
Expand Up @@ -155,6 +155,9 @@ public class ImageMap extends ImageView
// accounting for screen density
protected float densityFactor;

//possible to reduce memory consumption
protected BitmapFactory.Options options;

/*
* Constructors
*/
Expand Down Expand Up @@ -453,11 +456,30 @@ public void setImageBitmap(Bitmap bm)
}

@Override
public void setImageResource(int resId) {
Bitmap b = BitmapFactory.decodeResource(getResources(), resId);
setImageBitmap(b);
public void setImageResource(int resId)
{
final String imageKey = String.valueOf(resId);
BitmapHelper bitmapHelper = BitmapHelper.getInstance();
Bitmap bitmap = bitmapHelper.getBitmapFromMemCache(imageKey);

// 1 is the default setting, powers of 2 used to decrease image quality (and memory consumption)
// TODO: enable variable inSampleSize for low-memory devices
options = new BitmapFactory.Options();
options.inSampleSize = 1;

if (bitmap == null)
{
bitmap = BitmapFactory.decodeResource(getResources(), resId, options);
bitmapHelper.addBitmapToMemoryCache(imageKey, bitmap);
}
setImageBitmap(bitmap);
}

/*
setImageDrawable() is called by Android when the android:src attribute is set.
To avoid this and use the more flexible setImageResource(),
it is advised to omit the android:src attribute and call setImageResource() directly from code.
*/
@Override
public void setImageDrawable(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
Expand Down Expand Up @@ -1109,8 +1131,29 @@ void onScreenTapped(int x, int y)
int testx = x-mScrollLeft;
int testy = y-mScrollTop;

testx = (int)(((float)testx/mResizeFactorX)/densityFactor);
testy = (int)(((float)testy/mResizeFactorY)/densityFactor);
/*
Empirically, this works, but it's not guaranteed to be correct.
Seems that we need to divide by densityFactor only if the picture is larger than the screen.
When it is smaller than the screen, we don't need to do that.

TODO: investigate this in detail.
*/
if (mResizeFactorX > 1)
{
testx = (int)(((float)testx/mResizeFactorX));
}
else
{
testx = (int)(((float)testx/mResizeFactorX)/densityFactor);
}
if (mResizeFactorY > 1)
{
testy = (int)(((float)testy/mResizeFactorY));
}
else
{
testy = (int)(((float)testy/mResizeFactorY)/densityFactor);
}

// check if bubble tapped first
// in case a bubble covers an area we want it to
Expand Down
1 change: 1 addition & 0 deletions src/com/ctc/android/widget/ImageMapTestActivity.java
Expand Up @@ -30,6 +30,7 @@ public void onCreate(Bundle savedInstanceState) {

// find the image map in the view
mImageMap = (ImageMap)findViewById(R.id.map);
mImageMap.setImageResource(R.drawable.usamap);

// add a click handler to react when areas are tapped
mImageMap.addOnImageMapClickedHandler(new ImageMap.OnImageMapClickedHandler()
Expand Down