18e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard/*
28e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * Copyright (C) 2013 The Android Open Source Project
38e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard *
48e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * Licensed under the Apache License, Version 2.0 (the "License");
58e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * you may not use this file except in compliance with the License.
68e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * You may obtain a copy of the License at
78e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard *
88e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard *      http://www.apache.org/licenses/LICENSE-2.0
98e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard *
108e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * Unless required by applicable law or agreed to in writing, software
118e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * distributed under the License is distributed on an "AS IS" BASIS,
128e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * See the License for the specific language governing permissions and
148e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard * limitations under the License.
158e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard */
168e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
178e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroardpackage com.android.gallery3d.filtershow.pipeline;
188e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
198e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroardimport android.graphics.Bitmap;
208e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroardimport android.util.Log;
21ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard
22ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroardimport com.android.gallery3d.filtershow.cache.BitmapCache;
238e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroardimport com.android.gallery3d.filtershow.filters.FilterRepresentation;
24430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroardimport com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
258e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
26430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroardimport java.util.ArrayList;
278e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroardimport java.util.Vector;
288e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
298e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroardpublic class CacheProcessing {
308e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    private static final String LOGTAG = "CacheProcessing";
318e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    private static final boolean DEBUG = false;
321ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard    private static final boolean NO_CACHING = false;
338e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    private Vector<CacheStep> mSteps = new Vector<CacheStep>();
348e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
358e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    static class CacheStep {
36430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        ArrayList<FilterRepresentation> representations;
378e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        Bitmap cache;
38430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
39430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public CacheStep() {
40430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            representations = new ArrayList<FilterRepresentation>();
41430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
42430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
43430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public void add(FilterRepresentation representation) {
44430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            representations.add(representation);
45430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
46430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
47430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public boolean canMergeWith(FilterRepresentation representation) {
48430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            for (FilterRepresentation rep : representations) {
49430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                if (!rep.canMergeWith(representation)) {
50430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    return false;
51430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
52430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
53430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            return true;
54430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
55430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
56430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public boolean equals(CacheStep step) {
57430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            if (representations.size() != step.representations.size()) {
58430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                return false;
59430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
60430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            for (int i = 0; i < representations.size(); i++) {
61430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                FilterRepresentation r1 = representations.get(i);
62430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                FilterRepresentation r2 = step.representations.get(i);
63430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                if (!r1.equals(r2)) {
64430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    return false;
65430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
66430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
67430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            return true;
68430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
69430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
70430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public static Vector<CacheStep> buildSteps(Vector<FilterRepresentation> filters) {
71430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            Vector<CacheStep> steps = new Vector<CacheStep>();
72430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            CacheStep step = new CacheStep();
73430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            for (int i = 0; i < filters.size(); i++) {
74430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                FilterRepresentation representation = filters.elementAt(i);
75430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                if (step.canMergeWith(representation)) {
76430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    step.add(representation.copy());
77430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                } else {
78430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    steps.add(step);
79430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    step = new CacheStep();
80430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    step.add(representation.copy());
81430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
82430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
83430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            steps.add(step);
84430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            return steps;
85430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
86430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
87430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public String getName() {
88430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            if (representations.size() > 0) {
89430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                return representations.get(0).getName();
90430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
91430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            return "EMPTY";
92430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
93430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
94430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        public Bitmap apply(FilterEnvironment environment, Bitmap cacheBitmap) {
95430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            boolean onlyGeometry = true;
96ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            Bitmap source = cacheBitmap;
97430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            for (FilterRepresentation representation : representations) {
98430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
99430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    onlyGeometry = false;
100430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    break;
101430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
102430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
103430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            if (onlyGeometry) {
104430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                ArrayList<FilterRepresentation> geometry = new ArrayList<FilterRepresentation>();
105430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                for (FilterRepresentation representation : representations) {
106430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    geometry.add(representation);
107430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
1081ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                if (DEBUG) {
1091ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                    Log.v(LOGTAG, "Apply geometry to bitmap " + cacheBitmap);
1101ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                }
111430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                cacheBitmap = GeometryMathUtils.applyGeometryRepresentations(geometry, cacheBitmap);
112430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            } else {
113430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                for (FilterRepresentation representation : representations) {
1141ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                    if (DEBUG) {
1151ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                        Log.v(LOGTAG, "Apply " + representation.getSerializationName()
1161ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                                + " to bitmap " + cacheBitmap);
1171ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                    }
118430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    cacheBitmap = environment.applyRepresentation(representation, cacheBitmap);
119430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
120430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
121ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            if (cacheBitmap != source) {
122ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard                environment.cache(source);
123ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            }
1241ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            if (DEBUG) {
1251ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                Log.v(LOGTAG, "Apply returns bitmap " + cacheBitmap);
1261ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            }
127430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            return cacheBitmap;
128430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
1298e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    }
1308e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
1318e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    public Bitmap process(Bitmap originalBitmap,
1328e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard                          Vector<FilterRepresentation> filters,
1338e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard                          FilterEnvironment environment) {
1348f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard
1358f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard        if (filters.size() == 0) {
136ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            return environment.getBitmapCopy(originalBitmap, BitmapCache.PREVIEW_CACHE_NO_FILTERS);
1378f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard        }
1388e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
139c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        environment.getBimapCache().setCacheProcessing(this);
140c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard
141430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        if (DEBUG) {
142430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            displayFilters(filters);
143430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
144430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        Vector<CacheStep> steps = CacheStep.buildSteps(filters);
1458e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        // New set of filters, let's clear the cache and rebuild it.
146430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        if (steps.size() != mSteps.size()) {
147430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            mSteps = steps;
1488e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
1498e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
1508e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        if (DEBUG) {
151430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            displaySteps(mSteps);
1528e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
1538e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
1548e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        // First, let's find how similar we are in our cache
1558e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        // compared to the current list of filters
1568f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard        int similarUpToIndex = -1;
157430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        boolean similar = true;
158430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        for (int i = 0; i < steps.size(); i++) {
159430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            CacheStep newStep = steps.elementAt(i);
160430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            CacheStep cacheStep = mSteps.elementAt(i);
161430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            if (similar) {
162430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                similar = newStep.equals(cacheStep);
163430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            }
1648e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            if (similar) {
1658e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard                similarUpToIndex = i;
1668e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            } else {
167430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                mSteps.remove(i);
168430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                mSteps.insertElementAt(newStep, i);
169c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard                environment.cache(cacheStep.cache);
1708e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            }
1718e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
1728e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        if (DEBUG) {
1738e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            Log.v(LOGTAG, "similar up to index " + similarUpToIndex);
1748e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
1758e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
1768e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        // Now, let's get the earliest cached result in our pipeline
1778f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard        Bitmap cacheBitmap = null;
1788e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        int findBaseImageIndex = similarUpToIndex;
1798f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard        if (findBaseImageIndex > -1) {
1808f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard            while (findBaseImageIndex > 0
1818f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard                    && mSteps.elementAt(findBaseImageIndex).cache == null) {
1828f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard                findBaseImageIndex--;
1838f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard            }
1848f442fae60e0154867d2a6927eb9a35bcb7014e6nicolasroard            cacheBitmap = mSteps.elementAt(findBaseImageIndex).cache;
1858e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
1868e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
1878e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        if (DEBUG) {
188430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            Log.v(LOGTAG, "found baseImageIndex: " + findBaseImageIndex + " max is "
189430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    + mSteps.size() + " cacheBitmap: " + cacheBitmap);
1908e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
1918e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
1921ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard        if (NO_CACHING) {
1931ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            cacheBitmap = environment.getBitmapCopy(originalBitmap,
1941ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                    BitmapCache.PREVIEW_CACHE_NO_ROOT);
1951ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            for (int i = 0; i < mSteps.size(); i++) {
1961ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                CacheStep step = mSteps.elementAt(i);
1971ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                Bitmap prev = cacheBitmap;
1981ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                cacheBitmap = step.apply(environment, cacheBitmap);
1991ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                if (prev != cacheBitmap) {
2001ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                    environment.cache(prev);
2011ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard                }
2021ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            }
2031ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            return cacheBitmap;
2041ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard        }
2051ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard
2069f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard        Bitmap originalCopy = null;
207c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        int lastPositionCached = -1;
208430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        for (int i = findBaseImageIndex; i < mSteps.size(); i++) {
209430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            if (i == -1 || cacheBitmap == null) {
210ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard                cacheBitmap = environment.getBitmapCopy(originalBitmap,
211ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard                        BitmapCache.PREVIEW_CACHE_NO_ROOT);
2129f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard                originalCopy = cacheBitmap;
2138b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                if (DEBUG) {
2148b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                    Log.v(LOGTAG, "i: " + i + " cacheBitmap: " + cacheBitmap + " w: "
2158b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                            + cacheBitmap.getWidth() + " h: " + cacheBitmap.getHeight()
2168b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                            + " got from original Bitmap: " + originalBitmap + " w: "
2178b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                            + originalBitmap.getWidth() + " h: " + originalBitmap.getHeight());
2188b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                }
219430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                if (i == -1) {
220430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                    continue;
221430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                }
222b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk            }
223430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            CacheStep step = mSteps.elementAt(i);
224430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            if (step.cache == null) {
2258b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                if (DEBUG) {
2268b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                    Log.v(LOGTAG, "i: " + i + " get new copy for cacheBitmap "
2278b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                            + cacheBitmap + " apply...");
2288b9cc5f374fa8bded7f84af6ce73123be2754cccnicolasroard                }
229ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard                cacheBitmap = environment.getBitmapCopy(cacheBitmap, BitmapCache.PREVIEW_CACHE);
230430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                cacheBitmap = step.apply(environment, cacheBitmap);
231430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard                step.cache = cacheBitmap;
232c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard                lastPositionCached = i;
2338e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            }
2348e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
2359f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard        environment.cache(originalCopy);
2368e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
2378e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        if (DEBUG) {
2388e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            Log.v(LOGTAG, "now let's cleanup the cache...");
2398e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            displayNbBitmapsInCache();
2408e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
2418e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
2428e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        // Let's see if we can cleanup the cache for unused bitmaps
2438e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        for (int i = 0; i < similarUpToIndex; i++) {
2448e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            CacheStep currentStep = mSteps.elementAt(i);
245ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            Bitmap bitmap = currentStep.cache;
2468e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            currentStep.cache = null;
247ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            environment.cache(bitmap);
2488e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
2498e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
2508e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        if (DEBUG) {
2518e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            Log.v(LOGTAG, "cleanup done...");
2528e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            displayNbBitmapsInCache();
2538e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
254c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        if (lastPositionCached != -1) {
2551ebeed45d206ed306eb149e4e63242b1b55558efnicolasroard            // The last element will never be reused, remove it from the cache.
256c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard            mSteps.elementAt(lastPositionCached).cache = null;
257ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard        }
258ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard        if (contains(cacheBitmap)) {
259ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard            return environment.getBitmapCopy(cacheBitmap, BitmapCache.PREVIEW_CACHE_NO_APPLY);
260c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        }
2618e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        return cacheBitmap;
2628e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    }
2638e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
264c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard    public boolean contains(Bitmap bitmap) {
265c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        for (int i = 0; i < mSteps.size(); i++) {
266c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard            if (mSteps.elementAt(i).cache == bitmap) {
267c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard                return true;
268c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard            }
269c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        }
270c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard        return false;
271c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard    }
272c3d21101b14cdc1abf8a055e056019af57c4c7benicolasroard
2738e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    private void displayFilters(Vector<FilterRepresentation> filters) {
274430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        Log.v(LOGTAG, "------>>> Filters received");
275430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        for (int i = 0; i < filters.size(); i++) {
276430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            FilterRepresentation filter = filters.elementAt(i);
277430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            Log.v(LOGTAG, "[" + i + "] - " + filter.getName());
278430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        }
279430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard        Log.v(LOGTAG, "<<<------");
280430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard    }
281430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard
282430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard    private void displaySteps(Vector<CacheStep> filters) {
2838e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        Log.v(LOGTAG, "------>>>");
2848e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        for (int i = 0; i < filters.size(); i++) {
285430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            CacheStep newStep = filters.elementAt(i);
2868e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            CacheStep step = mSteps.elementAt(i);
287430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            boolean similar = step.equals(newStep);
288430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard            Log.v(LOGTAG, "[" + i + "] - " + step.getName()
2898e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard                    + " similar rep ? " + (similar ? "YES" : "NO")
2908e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard                    + " -- bitmap: " + step.cache);
2918e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
2928e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        Log.v(LOGTAG, "<<<------");
2938e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    }
2948e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
2958e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    private void displayNbBitmapsInCache() {
2968e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        int nbBitmapsCached = 0;
2978e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        for (int i = 0; i < mSteps.size(); i++) {
2988e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            CacheStep step = mSteps.elementAt(i);
2998e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            if (step.cache != null) {
3008e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard                nbBitmapsCached++;
3018e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard            }
3028e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        }
3038e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard        Log.v(LOGTAG, "nb bitmaps in cache: " + nbBitmapsCached + " / " + mSteps.size());
3048e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard    }
3058e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard
3068e33c2b402983070eb0cc9ace16ecfa4b9728447nicolasroard}
307