diff options
author | nicolasroard <nicolasroard@google.com> | 2013-08-01 16:22:30 -0700 |
---|---|---|
committer | nicolasroard <nicolasroard@google.com> | 2013-08-07 14:12:26 -0700 |
commit | 430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03 (patch) | |
tree | 5c679a659c48c718625d1c5a5049009927a2c617 /src/com/android/gallery3d/filtershow/pipeline | |
parent | 5843ba18bfd1ed81bdfde267af550aec30936a58 (diff) | |
download | android_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')
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(); } |