summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/pipeline
diff options
context:
space:
mode:
authornicolasroard <nicolasroard@google.com>2013-08-01 16:22:30 -0700
committernicolasroard <nicolasroard@google.com>2013-08-07 14:12:26 -0700
commit430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03 (patch)
tree5c679a659c48c718625d1c5a5049009927a2c617 /src/com/android/gallery3d/filtershow/pipeline
parent5843ba18bfd1ed81bdfde267af550aec30936a58 (diff)
downloadandroid_packages_apps_Gallery2-430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03.tar.gz
android_packages_apps_Gallery2-430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03.tar.bz2
android_packages_apps_Gallery2-430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03.zip
Fix full res zoom
Also add filters merging in the cache. Change-Id: Ic34c918b732159f3703cd83d30de907fdbbcb451
Diffstat (limited to 'src/com/android/gallery3d/filtershow/pipeline')
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java199
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java1
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java12
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/FullresRenderingRequestTask.java67
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java17
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java23
6 files changed, 234 insertions, 85 deletions
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
index e0269e9bb..7abeee723 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
@@ -19,7 +19,9 @@ package com.android.gallery3d.filtershow.pipeline;
import android.graphics.Bitmap;
import android.util.Log;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
+import java.util.ArrayList;
import java.util.Vector;
public class CacheProcessing {
@@ -28,8 +30,85 @@ public class CacheProcessing {
private Vector<CacheStep> mSteps = new Vector<CacheStep>();
static class CacheStep {
- FilterRepresentation representation;
+ ArrayList<FilterRepresentation> representations;
Bitmap cache;
+
+ public CacheStep() {
+ representations = new ArrayList<FilterRepresentation>();
+ }
+
+ public void add(FilterRepresentation representation) {
+ representations.add(representation);
+ }
+
+ public boolean canMergeWith(FilterRepresentation representation) {
+ for (FilterRepresentation rep : representations) {
+ if (!rep.canMergeWith(representation)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean equals(CacheStep step) {
+ if (representations.size() != step.representations.size()) {
+ return false;
+ }
+ for (int i = 0; i < representations.size(); i++) {
+ FilterRepresentation r1 = representations.get(i);
+ FilterRepresentation r2 = step.representations.get(i);
+ if (!r1.equals(r2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static Vector<CacheStep> buildSteps(Vector<FilterRepresentation> filters) {
+ Vector<CacheStep> steps = new Vector<CacheStep>();
+ CacheStep step = new CacheStep();
+ for (int i = 0; i < filters.size(); i++) {
+ FilterRepresentation representation = filters.elementAt(i);
+ if (step.canMergeWith(representation)) {
+ step.add(representation.copy());
+ } else {
+ steps.add(step);
+ step = new CacheStep();
+ step.add(representation.copy());
+ }
+ }
+ steps.add(step);
+ return steps;
+ }
+
+ public String getName() {
+ if (representations.size() > 0) {
+ return representations.get(0).getName();
+ }
+ return "EMPTY";
+ }
+
+ public Bitmap apply(FilterEnvironment environment, Bitmap cacheBitmap) {
+ boolean onlyGeometry = true;
+ for (FilterRepresentation representation : representations) {
+ if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
+ onlyGeometry = false;
+ break;
+ }
+ }
+ if (onlyGeometry) {
+ ArrayList<FilterRepresentation> geometry = new ArrayList<FilterRepresentation>();
+ for (FilterRepresentation representation : representations) {
+ geometry.add(representation);
+ }
+ cacheBitmap = GeometryMathUtils.applyGeometryRepresentations(geometry, cacheBitmap);
+ } else {
+ for (FilterRepresentation representation : representations) {
+ cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
+ }
+ }
+ return cacheBitmap;
+ }
}
public Bitmap process(Bitmap originalBitmap,
@@ -40,32 +119,34 @@ public class CacheProcessing {
return originalBitmap;
}
+ if (DEBUG) {
+ displayFilters(filters);
+ }
+ Vector<CacheStep> steps = CacheStep.buildSteps(filters);
// New set of filters, let's clear the cache and rebuild it.
- if (filters.size() != mSteps.size()) {
- mSteps.clear();
- for (int i = 0; i < filters.size(); i++) {
- FilterRepresentation representation = filters.elementAt(i);
- CacheStep step = new CacheStep();
- step.representation = representation.copy();
- mSteps.add(step);
- }
+ if (steps.size() != mSteps.size()) {
+ mSteps = steps;
}
if (DEBUG) {
- displayFilters(filters);
+ displaySteps(mSteps);
}
// First, let's find how similar we are in our cache
// compared to the current list of filters
int similarUpToIndex = -1;
- for (int i = 0; i < filters.size(); i++) {
- FilterRepresentation representation = filters.elementAt(i);
- CacheStep step = mSteps.elementAt(i);
- boolean similar = step.representation.equals(representation);
+ boolean similar = true;
+ for (int i = 0; i < steps.size(); i++) {
+ CacheStep newStep = steps.elementAt(i);
+ CacheStep cacheStep = mSteps.elementAt(i);
+ if (similar) {
+ similar = newStep.equals(cacheStep);
+ }
if (similar) {
similarUpToIndex = i;
} else {
- break;
+ mSteps.remove(i);
+ mSteps.insertElementAt(newStep, i);
}
}
if (DEBUG) {
@@ -82,69 +163,25 @@ public class CacheProcessing {
}
cacheBitmap = mSteps.elementAt(findBaseImageIndex).cache;
}
- boolean emptyStack = false;
- if (cacheBitmap == null) {
- emptyStack = true;
- // Damn, it's an empty stack, we have to start from scratch
- // TODO: use a bitmap cache + RS allocation instead of Bitmap.copy()
- cacheBitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
- if (findBaseImageIndex > -1) {
- FilterRepresentation representation = filters.elementAt(findBaseImageIndex);
- if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
- cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
- }
- mSteps.elementAt(findBaseImageIndex).representation = representation.copy();
- mSteps.elementAt(findBaseImageIndex).cache = cacheBitmap;
- }
- if (DEBUG) {
- Log.v(LOGTAG, "empty stack");
- }
- }
-
- // Ok, so sadly the earliest cached result is before the index we want.
- // We have to rebuild a new result for this position, and then cache it.
- if (findBaseImageIndex != similarUpToIndex) {
- if (DEBUG) {
- Log.v(LOGTAG, "rebuild cacheBitmap from " + findBaseImageIndex
- + " to " + similarUpToIndex);
- }
- // rebuild the cache image for this step
- if (!emptyStack) {
- cacheBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true);
- } else {
- // if it was an empty stack, we already applied it
- findBaseImageIndex ++;
- }
- for (int i = findBaseImageIndex; i <= similarUpToIndex; i++) {
- FilterRepresentation representation = filters.elementAt(i);
- if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
- cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
- }
- if (DEBUG) {
- Log.v(LOGTAG, " - " + i + " => apply " + representation.getName());
- }
- }
- // Let's cache it!
- mSteps.elementAt(similarUpToIndex).cache = cacheBitmap;
- }
if (DEBUG) {
- Log.v(LOGTAG, "process pipeline from " + similarUpToIndex
- + " to " + (filters.size() - 1));
+ Log.v(LOGTAG, "found baseImageIndex: " + findBaseImageIndex + " max is "
+ + mSteps.size() + " cacheBitmap: " + cacheBitmap);
}
- // Now we are good to go, let's use the cacheBitmap as a starting point
- for (int i = similarUpToIndex + 1; i < filters.size(); i++) {
- FilterRepresentation representation = filters.elementAt(i);
- CacheStep currentStep = mSteps.elementAt(i);
- cacheBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true);
- if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
- cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
+ for (int i = findBaseImageIndex; i < mSteps.size(); i++) {
+ if (i == -1 || cacheBitmap == null) {
+ cacheBitmap = environment.getBitmapCopy(originalBitmap);
+ if (i == -1) {
+ continue;
+ }
}
- currentStep.representation = representation.copy();
- currentStep.cache = cacheBitmap;
- if (DEBUG) {
- Log.v(LOGTAG, " - " + i + " => apply " + representation.getName());
+ CacheStep step = mSteps.elementAt(i);
+ if (step.cache == null) {
+ cacheBitmap = environment.getBitmapCopy(cacheBitmap);
+ cacheBitmap = step.apply(environment, cacheBitmap);
+ environment.cache(step.cache);
+ step.cache = cacheBitmap;
}
}
@@ -156,6 +193,7 @@ public class CacheProcessing {
// Let's see if we can cleanup the cache for unused bitmaps
for (int i = 0; i < similarUpToIndex; i++) {
CacheStep currentStep = mSteps.elementAt(i);
+ environment.cache(currentStep.cache);
currentStep.cache = null;
}
@@ -167,12 +205,21 @@ public class CacheProcessing {
}
private void displayFilters(Vector<FilterRepresentation> filters) {
+ Log.v(LOGTAG, "------>>> Filters received");
+ for (int i = 0; i < filters.size(); i++) {
+ FilterRepresentation filter = filters.elementAt(i);
+ Log.v(LOGTAG, "[" + i + "] - " + filter.getName());
+ }
+ Log.v(LOGTAG, "<<<------");
+ }
+
+ private void displaySteps(Vector<CacheStep> filters) {
Log.v(LOGTAG, "------>>>");
for (int i = 0; i < filters.size(); i++) {
- FilterRepresentation representation = filters.elementAt(i);
+ CacheStep newStep = filters.elementAt(i);
CacheStep step = mSteps.elementAt(i);
- boolean similar = step.representation.equals(representation);
- Log.v(LOGTAG, "[" + i + "] - " + representation.getName()
+ boolean similar = step.equals(newStep);
+ Log.v(LOGTAG, "[" + i + "] - " + step.getName()
+ " similar rep ? " + (similar ? "YES" : "NO")
+ " -- bitmap: " + step.cache);
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
index fc0d6ce49..932e2fc00 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java
@@ -348,6 +348,7 @@ public class CachingPipeline implements PipelineInterface {
}
setupEnvironment(preset, false);
Vector<FilterRepresentation> filters = preset.getFilters();
+ mEnvironment.cache(buffer.getProducer()); // the producer bitmap isn't needed anymore
Bitmap result = mCachedProcessing.process(mOriginalBitmap, filters, mEnvironment);
buffer.setProducer(result);
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
index 4fac956be..c5c665360 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
@@ -17,6 +17,7 @@
package com.android.gallery3d.filtershow.pipeline;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
@@ -63,6 +64,10 @@ public class FilterEnvironment {
return;
}
Bitmap bitmap = buffer.getBitmap();
+ cache(bitmap);
+ }
+
+ public void cache(Bitmap bitmap) {
if (bitmap == null) {
return;
}
@@ -84,6 +89,13 @@ public class FilterEnvironment {
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 << 32);
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FullresRenderingRequestTask.java b/src/com/android/gallery3d/filtershow/pipeline/FullresRenderingRequestTask.java
new file mode 100644
index 000000000..ab72c8d2b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/pipeline/FullresRenderingRequestTask.java
@@ -0,0 +1,67 @@
+package com.android.gallery3d.filtershow.pipeline;
+
+import android.graphics.Bitmap;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+
+public class FullresRenderingRequestTask extends ProcessingTask {
+
+ private CachingPipeline mFullresPipeline = null;
+ private boolean mPipelineIsOn = false;
+
+ public void setPreviewScaleFactor(float previewScale) {
+ mFullresPipeline.setPreviewScaleFactor(previewScale);
+ }
+
+ static class Render implements Request {
+ RenderingRequest request;
+ }
+
+ static class RenderResult implements Result {
+ RenderingRequest request;
+ }
+
+ public FullresRenderingRequestTask() {
+ mFullresPipeline = new CachingPipeline(
+ FiltersManager.getHighresManager(), "Fullres");
+ }
+
+ public void setOriginal(Bitmap bitmap) {
+ mFullresPipeline.setOriginal(bitmap);
+ mPipelineIsOn = true;
+ }
+
+ public void stop() {
+ mFullresPipeline.stop();
+ }
+
+ public void postRenderingRequest(RenderingRequest request) {
+ if (!mPipelineIsOn) {
+ return;
+ }
+ Render render = new Render();
+ render.request = request;
+ postRequest(render);
+ }
+
+ @Override
+ public Result doInBackground(Request message) {
+ RenderingRequest request = ((Render) message).request;
+ RenderResult result = null;
+ mFullresPipeline.render(request);
+ result = new RenderResult();
+ result.request = request;
+ return result;
+ }
+
+ @Override
+ public void onResult(Result message) {
+ if (message == null) {
+ return;
+ }
+ RenderingRequest request = ((RenderResult) message).request;
+ request.markAvailable();
+ }
+
+ @Override
+ public boolean isDelayedTask() { return true; }
+}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
index d34216ad6..e28cc356b 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
@@ -306,8 +306,15 @@ public class ImagePreset {
mFilters.remove(i);
}
}
+ int index = 0;
+ for (; index < mFilters.size(); index++) {
+ FilterRepresentation rep = mFilters.elementAt(index);
+ if (rep.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
+ break;
+ }
+ }
if (!representation.isNil()) {
- mFilters.add(representation);
+ mFilters.insertElementAt(representation, index);
}
} else if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
removeFilter(representation);
@@ -524,10 +531,6 @@ public class ImagePreset {
}
for (int i = 0; i < mFilters.size(); i++) {
FilterRepresentation representation = mFilters.elementAt(i);
- if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY
- && !representation.isNil()) {
- return false;
- }
if (!representation.supportsPartialRendering()) {
return false;
}
@@ -541,10 +544,6 @@ public class ImagePreset {
}
Vector<State> states = new Vector<State>();
for (FilterRepresentation filter : mFilters) {
- if (filter.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
- // TODO: supports Geometry representations in the state panel.
- continue;
- }
if (filter instanceof FilterUserPresetRepresentation) {
// do not show the user preset itself in the state panel
continue;
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
index d0504d11f..4f736f868 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
@@ -55,6 +56,7 @@ public class ProcessingService extends Service {
private ImageSavingTask mImageSavingTask;
private UpdatePreviewTask mUpdatePreviewTask;
private HighresRenderingRequestTask mHighresRenderingRequestTask;
+ private FullresRenderingRequestTask mFullresRenderingRequestTask;
private RenderingRequestTask mRenderingRequestTask;
private final IBinder mBinder = new LocalBinder();
@@ -73,11 +75,13 @@ public class ProcessingService extends Service {
}
mUpdatePreviewTask.setOriginal(originalBitmap);
mHighresRenderingRequestTask.setOriginal(originalBitmap);
+ mFullresRenderingRequestTask.setOriginal(originalBitmap);
mRenderingRequestTask.setOriginal(originalBitmap);
}
public void updatePreviewBuffer() {
mHighresRenderingRequestTask.stop();
+ mFullresRenderingRequestTask.stop();
mUpdatePreviewTask.updatePreview();
}
@@ -98,12 +102,29 @@ public class ProcessingService extends Service {
mHighresRenderingRequestTask.postRenderingRequest(request);
}
+ public void postFullresRenderingRequest(ImagePreset preset, float scaleFactor,
+ Rect bounds, Rect destination,
+ RenderingRequestCaller caller) {
+ RenderingRequest request = new RenderingRequest();
+ ImagePreset passedPreset = new ImagePreset(preset);
+ request.setOriginalImagePreset(preset);
+ request.setScaleFactor(scaleFactor);
+ request.setImagePreset(passedPreset);
+ request.setType(RenderingRequest.PARTIAL_RENDERING);
+ request.setCaller(caller);
+ request.setBounds(bounds);
+ request.setDestination(destination);
+ passedPreset.setPartialRendering(true, bounds);
+ mFullresRenderingRequestTask.postRenderingRequest(request);
+ }
+
public void setHighresPreviewScaleFactor(float highResPreviewScale) {
mHighresRenderingRequestTask.setHighresPreviewScaleFactor(highResPreviewScale);
}
public void setPreviewScaleFactor(float previewScale) {
mHighresRenderingRequestTask.setPreviewScaleFactor(previewScale);
+ mFullresRenderingRequestTask.setPreviewScaleFactor(previewScale);
mRenderingRequestTask.setPreviewScaleFactor(previewScale);
}
@@ -144,10 +165,12 @@ public class ProcessingService extends Service {
mImageSavingTask = new ImageSavingTask(this);
mUpdatePreviewTask = new UpdatePreviewTask();
mHighresRenderingRequestTask = new HighresRenderingRequestTask();
+ mFullresRenderingRequestTask = new FullresRenderingRequestTask();
mRenderingRequestTask = new RenderingRequestTask();
mProcessingTaskController.add(mImageSavingTask);
mProcessingTaskController.add(mUpdatePreviewTask);
mProcessingTaskController.add(mHighresRenderingRequestTask);
+ mProcessingTaskController.add(mFullresRenderingRequestTask);
mProcessingTaskController.add(mRenderingRequestTask);
setupPipeline();
}