summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/gallery3d/filtershow/cache/BitmapCache.java96
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java49
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java4
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/MasterImage.java9
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/Buffer.java18
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java3
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java5
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java44
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java5
9 files changed, 181 insertions, 52 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
new file mode 100644
index 000000000..bd1130d26
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 com.android.gallery3d.filtershow.cache;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.util.Log;
+import com.android.gallery3d.filtershow.pipeline.Buffer;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class BitmapCache {
+ private static final String LOGTAG = "BitmapCache";
+ private HashMap<Long, ArrayList<WeakReference<Bitmap>>>
+ mBitmapCache = new HashMap<Long, ArrayList<WeakReference<Bitmap>>>();
+ private final int mMaxItemsPerKey = 4;
+
+ public void cache(Buffer buffer) {
+ if (buffer == null) {
+ return;
+ }
+ Bitmap bitmap = buffer.getBitmap();
+ cache(bitmap);
+ }
+
+ public synchronized void cache(Bitmap bitmap) {
+ if (bitmap == null) {
+ return;
+ }
+ Long key = calcKey(bitmap.getWidth(), bitmap.getHeight());
+ ArrayList<WeakReference<Bitmap>> list = mBitmapCache.get(key);
+ if (list == null) {
+ list = new ArrayList<WeakReference<Bitmap>>();
+ mBitmapCache.put(key, list);
+ }
+ if (list.size() < mMaxItemsPerKey) {
+ for (int i = 0; i < list.size(); i++) {
+ WeakReference<Bitmap> ref = list.get(i);
+ if (ref.get() == bitmap) {
+ return; // bitmap already in the cache
+ }
+ }
+ list.add(new WeakReference<Bitmap>(bitmap));
+ }
+ }
+
+ public synchronized Bitmap getBitmap(int w, int h) {
+ Long key = calcKey(w, h);
+ WeakReference<Bitmap> ref = null; //mBitmapCache.remove(key);
+ ArrayList<WeakReference<Bitmap>> list = mBitmapCache.get(key);
+ if (list != null && list.size() > 0) {
+ ref = list.remove(0);
+ if (list.size() == 0) {
+ mBitmapCache.remove(key);
+ }
+ }
+ Bitmap bitmap = null;
+ if (ref != null) {
+ bitmap = ref.get();
+ }
+ if (bitmap == null
+ || bitmap.getWidth() != w
+ || bitmap.getHeight() != h) {
+ bitmap = Bitmap.createBitmap(
+ w, h, Bitmap.Config.ARGB_8888);
+ }
+ return bitmap;
+ }
+
+ public Bitmap getBitmapCopy(Bitmap source) {
+ Bitmap bitmap = getBitmap(source.getWidth(), source.getHeight());
+ Canvas canvas = new Canvas(bitmap);
+ canvas.drawBitmap(source, 0, 0, null);
+ return bitmap;
+ }
+
+ private Long calcKey(long w, long h) {
+ return (w << 32) | h;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index 3877c4980..15ffb1814 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -24,7 +24,9 @@ import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
import android.provider.MediaStore;
@@ -37,6 +39,7 @@ import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
import com.android.gallery3d.filtershow.tools.XmpPresets;
import com.android.gallery3d.util.XmpUtilHelper;
@@ -230,22 +233,50 @@ public final class ImageLoader {
* if it is a subset of the bitmap stored at uri. Otherwise returns
* null.
*/
- public static Bitmap loadRegionBitmap(Context context, Uri uri, BitmapFactory.Options options,
- Rect bounds) {
+ public static Bitmap loadRegionBitmap(Context context, FilterEnvironment environment,
+ Uri uri, BitmapFactory.Options options,
+ Rect bounds) {
InputStream is = null;
+ int w = 0;
+ int h = 0;
+ if (options.inSampleSize != 0) {
+ return null;
+ }
try {
is = context.getContentResolver().openInputStream(uri);
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
+ w = decoder.getWidth();
+ h = decoder.getHeight();
+ Rect imageBounds = new Rect(bounds);
// return null if bounds are not entirely within the bitmap
- if (!r.contains(bounds)) {
- return null;
+ if (!r.contains(imageBounds)) {
+ imageBounds.intersect(r);
}
- return decoder.decodeRegion(bounds, options);
+ Bitmap reuse = environment.getBitmap(imageBounds.width(), imageBounds.height());
+ options.inBitmap = reuse;
+ Bitmap bitmap = decoder.decodeRegion(imageBounds, options);
+ if (bitmap != reuse) {
+ environment.cache(reuse); // not reused, put back in cache
+ }
+ if (imageBounds.width() != bounds.width() || imageBounds.height() != bounds.height()) {
+ Bitmap temp = environment.getBitmap(bounds.width(), bounds.height());
+ Canvas canvas = new Canvas(temp);
+ canvas.drawARGB(0, 0, 0, 0);
+ float dx = imageBounds.left - bounds.left;
+ float dy = imageBounds.top - bounds.top;
+ canvas.drawBitmap(bitmap, dx, dy, null);
+ return temp;
+ }
+ return bitmap;
} catch (FileNotFoundException e) {
Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
} catch (IOException e) {
Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
+ } catch (IllegalArgumentException e) {
+ Log.e(LOGTAG, "exc, image decoded " + w + " x " + h + " bounds: "
+ + bounds.left + "," + bounds.top + " - "
+ + bounds.width() + "x" + bounds.height() + " exc: " + e);
} finally {
Utils.closeSilently(is);
}
@@ -365,8 +396,10 @@ public final class ImageLoader {
return bmap;
}
- public static Bitmap getScaleOneImageForPreset(Context context, Uri uri, Rect bounds,
- Rect destination) {
+ public static Bitmap getScaleOneImageForPreset(Context context,
+ FilterEnvironment environment,
+ Uri uri, Rect bounds,
+ Rect destination) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
if (destination != null) {
@@ -380,7 +413,7 @@ public final class ImageLoader {
options.inSampleSize = sampleSize;
}
}
- Bitmap bmp = loadRegionBitmap(context, uri, options, bounds);
+ Bitmap bmp = loadRegionBitmap(context, environment, uri, options, bounds);
return bmp;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index b0352de3d..2bb269e29 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -197,7 +197,9 @@ public class ImageShow extends View implements OnGestureListener,
@Override
public void onDraw(Canvas canvas) {
- MasterImage.getImage().setImageShowSize(getWidth(), getHeight());
+ MasterImage.getImage().setImageShowSize(
+ getWidth() - 2*mShadowMargin,
+ getHeight() - 2*mShadowMargin);
float cx = canvas.getWidth()/2.0f;
float cy = canvas.getHeight()/2.0f;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index 2d84f40f8..7e17bd470 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -27,6 +27,7 @@ import android.os.Message;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -94,6 +95,7 @@ public class MasterImage implements RenderingRequestCaller {
private boolean mShowsOriginal;
private List<ExifTag> mEXIF;
+ private BitmapCache mBitmapCache = new BitmapCache();
private MasterImage() {
}
@@ -371,6 +373,7 @@ public class MasterImage implements RenderingRequestCaller {
public void invalidatePartialPreview() {
if (mPartialBitmap != null) {
+ mBitmapCache.cache(mPartialBitmap);
mPartialBitmap = null;
notifyObservers();
}
@@ -378,6 +381,7 @@ public class MasterImage implements RenderingRequestCaller {
public void invalidateHighresPreview() {
if (mHighresBitmap != null) {
+ mBitmapCache.cache(mHighresBitmap);
mHighresBitmap = null;
notifyObservers();
}
@@ -476,11 +480,13 @@ public class MasterImage implements RenderingRequestCaller {
}
if (request.getType() == RenderingRequest.PARTIAL_RENDERING
&& request.getScaleFactor() == getScaleFactor()) {
+ mBitmapCache.cache(mPartialBitmap);
mPartialBitmap = request.getBitmap();
notifyObservers();
needsCheckModification = true;
}
if (request.getType() == RenderingRequest.HIGHRES_RENDERING) {
+ mBitmapCache.cache(mHighresBitmap);
mHighresBitmap = request.getBitmap();
notifyObservers();
needsCheckModification = true;
@@ -586,4 +592,7 @@ public class MasterImage implements RenderingRequestCaller {
return mEXIF;
}
+ public BitmapCache getBitmapCache() {
+ return mBitmapCache;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
index 744451229..7b51a75d7 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
@@ -19,19 +19,23 @@ package com.android.gallery3d.filtershow.pipeline;
import android.graphics.Bitmap;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.RenderScript;
+import android.util.Log;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
public class Buffer {
private static final String LOGTAG = "Buffer";
private Bitmap mBitmap;
private Allocation mAllocation;
private boolean mUseAllocation = false;
- private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private ImagePreset mPreset;
public Buffer(Bitmap bitmap) {
RenderScript rs = CachingPipeline.getRenderScriptContext();
if (bitmap != null) {
- mBitmap = bitmap.copy(BITMAP_CONFIG, true);
+ BitmapCache cache = MasterImage.getImage().getBitmapCache();
+ cache.cache(mBitmap);
+ mBitmap = cache.getBitmapCopy(bitmap);
}
if (mUseAllocation) {
// TODO: recreate the allocation when the RS context changes
@@ -41,10 +45,6 @@ public class Buffer {
}
}
- public void setBitmap(Bitmap bitmap) {
- mBitmap = bitmap.copy(BITMAP_CONFIG, true);
- }
-
public Bitmap getBitmap() {
return mBitmap;
}
@@ -70,5 +70,11 @@ public class Buffer {
mPreset.updateWith(preset);
}
}
+
+ public void remove() {
+ BitmapCache cache = MasterImage.getImage().getBitmapCache();
+ cache.cache(mBitmap);
+ mBitmap = null;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
index edd07d226..8f6eda261 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
@@ -145,6 +145,7 @@ public class CacheProcessing {
if (similar) {
similarUpToIndex = i;
} else {
+ environment.cache(cacheStep.cache);
mSteps.remove(i);
mSteps.insertElementAt(newStep, i);
}
@@ -188,9 +189,9 @@ public class CacheProcessing {
Log.v(LOGTAG, "i: " + i + " get new copy for cacheBitmap "
+ cacheBitmap + " apply...");
}
+ environment.cache(step.cache);
cacheBitmap = environment.getBitmapCopy(cacheBitmap);
cacheBitmap = step.apply(environment, cacheBitmap);
- environment.cache(step.cache);
step.cache = cacheBitmap;
}
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
index 932e2fc00..0794277b0 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
@@ -157,6 +157,7 @@ public class CachingPipeline implements PipelineInterface {
private void setupEnvironment(ImagePreset preset, boolean highResPreview) {
mEnvironment.setPipeline(this);
mEnvironment.setFiltersManager(mFiltersManager);
+ mEnvironment.setBitmapCache(MasterImage.getImage().getBitmapCache());
if (highResPreview) {
mEnvironment.setScaleFactor(mHighResPreviewScaleFactor);
} else {
@@ -213,8 +214,7 @@ public class CachingPipeline implements PipelineInterface {
if (bitmap == null) {
return;
}
- // TODO: use a cache of bitmaps
- bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
+ bitmap = mEnvironment.getBitmapCopy(bitmap);
bitmap = preset.applyGeometry(bitmap, mEnvironment);
mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW);
@@ -251,6 +251,7 @@ public class CachingPipeline implements PipelineInterface {
if (request.getType() == RenderingRequest.PARTIAL_RENDERING) {
MasterImage master = MasterImage.getImage();
bitmap = ImageLoader.getScaleOneImageForPreset(master.getActivity(),
+ mEnvironment,
master.getUri(), request.getBounds(),
request.getDestination());
if (bitmap == null) {
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
index b540d96dd..2757aff11 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.support.v8.renderscript.Allocation;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManagerInterface;
@@ -36,6 +37,7 @@ public class FilterEnvironment {
private FiltersManagerInterface mFiltersManager;
private PipelineInterface mPipeline;
private volatile boolean mStop = false;
+ private BitmapCache mBitmapCache;
public static final int QUALITY_ICON = 0;
public static final int QUALITY_PREVIEW = 1;
@@ -49,53 +51,27 @@ public class FilterEnvironment {
this.mStop = stop;
}
- private HashMap<Long, WeakReference<Bitmap>>
- bitmapCach = new HashMap<Long, WeakReference<Bitmap>>();
-
private HashMap<Integer, Integer>
generalParameters = new HashMap<Integer, Integer>();
+ public void setBitmapCache(BitmapCache cache) {
+ mBitmapCache = cache;
+ }
+
public void cache(Buffer buffer) {
- if (buffer == null) {
- return;
- }
- Bitmap bitmap = buffer.getBitmap();
- cache(bitmap);
+ mBitmapCache.cache(buffer);
}
public void cache(Bitmap bitmap) {
- if (bitmap == null) {
- return;
- }
- Long key = calcKey(bitmap.getWidth(), bitmap.getHeight());
- bitmapCach.put(key, new WeakReference<Bitmap>(bitmap));
+ mBitmapCache.cache(bitmap);
}
public Bitmap getBitmap(int w, int h) {
- Long key = calcKey(w, h);
- WeakReference<Bitmap> ref = bitmapCach.remove(key);
- Bitmap bitmap = null;
- if (ref != null) {
- bitmap = ref.get();
- }
- if (bitmap == null
- || bitmap.getWidth() != w
- || bitmap.getHeight() != h) {
- bitmap = Bitmap.createBitmap(
- w, h, Bitmap.Config.ARGB_8888);
- }
- return bitmap;
+ return mBitmapCache.getBitmap(w, h);
}
public Bitmap getBitmapCopy(Bitmap source) {
- Bitmap bitmap = getBitmap(source.getWidth(), source.getHeight());
- Canvas canvas = new Canvas(bitmap);
- canvas.drawBitmap(source, 0, 0, null);
- return bitmap;
- }
-
- private Long calcKey(long w, long h) {
- return (w << 32) | h;
+ return mBitmapCache.getBitmapCopy(source);
}
public void setImagePreset(ImagePreset imagePreset) {
diff --git a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java b/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
index 98e69f60e..871e4cd6c 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
@@ -30,6 +30,11 @@ public class SharedBuffer {
private volatile boolean mNeedsRepaint = true;
public void setProducer(Bitmap producer) {
+ synchronized (this) {
+ if (mProducer != null) {
+ mProducer.remove();
+ }
+ }
Buffer buffer = new Buffer(producer);
synchronized (this) {
mProducer = buffer;