ImagePreset.java revision 2562a98c156a55b51239fea383838a11a0292c0e
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gallery3d.filtershow.presets;
18
19import android.graphics.Bitmap;
20import android.util.Log;
21
22import com.android.gallery3d.filtershow.ImageStateAdapter;
23import com.android.gallery3d.filtershow.cache.ImageLoader;
24import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
25import com.android.gallery3d.filtershow.filters.FilterRepresentation;
26import com.android.gallery3d.filtershow.filters.FiltersManager;
27import com.android.gallery3d.filtershow.filters.ImageFilter;
28import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
29import com.android.gallery3d.filtershow.imageshow.MasterImage;
30
31import java.util.Vector;
32
33public class ImagePreset {
34
35    private static final String LOGTAG = "ImagePreset";
36
37    private FilterRepresentation mBorder = null;
38    private float mScaleFactor = 1.0f;
39    public static final int QUALITY_ICON = 0;
40    public static final int QUALITY_PREVIEW = 1;
41    public static final int QUALITY_FINAL = 2;
42    private int mQuality = QUALITY_PREVIEW;
43    private ImageLoader mImageLoader = null;
44
45    private Vector<FilterRepresentation> mFilters = new Vector<FilterRepresentation>();
46
47    protected String mName = "Original";
48    private String mHistoryName = "Original";
49    protected boolean mIsFxPreset = false;
50
51    private boolean mDoApplyGeometry = true;
52    private boolean mDoApplyFilters = true;
53
54    public final GeometryMetadata mGeoData = new GeometryMetadata();
55
56    public ImagePreset() {
57        setup();
58    }
59
60    public ImagePreset(String historyName) {
61        setHistoryName(historyName);
62        setup();
63    }
64
65    public ImagePreset(ImagePreset source, String historyName) {
66        this(source);
67        if (historyName != null) {
68            setHistoryName(historyName);
69        }
70    }
71
72    public ImagePreset(ImagePreset source) {
73        try {
74            if (source.mBorder != null) {
75                mBorder = source.mBorder.clone();
76            }
77            for (int i = 0; i < source.mFilters.size(); i++) {
78                FilterRepresentation representation = source.mFilters.elementAt(i).clone();
79                representation.setImagePreset(this);
80                addFilter(representation);
81            }
82        } catch (java.lang.CloneNotSupportedException e) {
83            Log.v(LOGTAG, "Exception trying to clone: " + e);
84        }
85        mName = source.name();
86        mHistoryName = source.name();
87        mIsFxPreset = source.isFx();
88        mImageLoader = source.getImageLoader();
89
90        mGeoData.set(source.mGeoData);
91    }
92
93    public FilterRepresentation getFilterRepresentation(int position) {
94        FilterRepresentation representation = null;
95        try {
96            representation = mFilters.elementAt(position).clone();
97        } catch (CloneNotSupportedException e) {
98            e.printStackTrace();
99        }
100        return representation;
101    }
102
103    public int getPositionForRepresentation(FilterRepresentation representation) {
104        for (int i = 0; i < mFilters.size(); i++) {
105            if (mFilters.elementAt(i).getFilterClass() == representation.getFilterClass()) {
106                return i;
107            }
108        }
109        return -1;
110    }
111
112    public FilterRepresentation getFilterRepresentationCopyFrom(FilterRepresentation filterRepresentation) {
113        // TODO: add concept of position in the filters (to allow multiple instances)
114        if (filterRepresentation == null) {
115            return null;
116        }
117        int position = getPositionForRepresentation(filterRepresentation);
118        if (position == -1) {
119            return null;
120        }
121        FilterRepresentation representation = null;
122        try {
123            representation = mFilters.elementAt(position).clone();
124        } catch (CloneNotSupportedException e) {
125            e.printStackTrace();
126        }
127        return representation;
128    }
129
130    public void updateFilterRepresentation(FilterRepresentation representation) {
131        synchronized (mFilters) {
132            int position = getPositionForRepresentation(representation);
133            FilterRepresentation old = mFilters.elementAt(position);
134            old.useParametersFrom(representation);
135        }
136        MasterImage.getImage().invalidatePreview();
137    }
138
139    public void setDoApplyGeometry(boolean value) {
140        mDoApplyGeometry = value;
141    }
142
143    public void setDoApplyFilters(boolean value) {
144        mDoApplyFilters = value;
145    }
146
147    public boolean getDoApplyFilters() {
148        return mDoApplyFilters;
149    }
150
151    public synchronized GeometryMetadata getGeometry() {
152        return mGeoData;
153    }
154
155    public boolean hasModifications() {
156        if (mBorder != null && !mBorder.isNil()) {
157            return true;
158        }
159        if (mGeoData.hasModifications()) {
160            return true;
161        }
162        for (int i = 0; i < mFilters.size(); i++) {
163            FilterRepresentation filter = mFilters.elementAt(i);
164            if (!filter.isNil()) {
165                return true;
166            }
167        }
168        return false;
169    }
170
171    public boolean isPanoramaSafe() {
172        if (mBorder != null && !mBorder.isNil()) {
173            return false;
174        }
175        if (mGeoData.hasModifications()) {
176            return false;
177        }
178        for (FilterRepresentation representation : mFilters) {
179            if (representation.getPriority() == FilterRepresentation.TYPE_VIGNETTE
180                && !representation.isNil()) {
181                return false;
182            }
183            if (representation.getPriority() == FilterRepresentation.TYPE_TINYPLANET
184                && !representation.isNil()) {
185                return false;
186            }
187        }
188        return true;
189    }
190
191    public synchronized void setGeometry(GeometryMetadata m) {
192        mGeoData.set(m);
193    }
194
195    private void setBorder(FilterRepresentation filter) {
196        mBorder = filter;
197    }
198
199    public boolean isFx() {
200        return mIsFxPreset;
201    }
202
203    public void setIsFx(boolean value) {
204        mIsFxPreset = value;
205    }
206
207    public void setName(String name) {
208        mName = name;
209        mHistoryName = name;
210    }
211
212    public void setHistoryName(String name) {
213        mHistoryName = name;
214    }
215
216    public ImageLoader getImageLoader() {
217        return mImageLoader;
218    }
219
220    public void setImageLoader(ImageLoader mImageLoader) {
221        this.mImageLoader = mImageLoader;
222    }
223
224    public boolean equals(ImagePreset preset) {
225        if (!same(preset)) {
226            return false;
227        }
228        if (mDoApplyFilters && preset.mDoApplyFilters) {
229            for (int i = 0; i < preset.mFilters.size(); i++) {
230                FilterRepresentation a = preset.mFilters.elementAt(i);
231                FilterRepresentation b = mFilters.elementAt(i);
232                if (!a.equals(b)) {
233                    return false;
234                }
235            }
236        }
237        return true;
238    }
239
240    public boolean same(ImagePreset preset) {
241        if (preset == null) {
242            return false;
243        }
244
245        if (preset.mFilters.size() != mFilters.size()) {
246            return false;
247        }
248
249        if (!mName.equalsIgnoreCase(preset.name())) {
250            return false;
251        }
252
253        if (mDoApplyGeometry != preset.mDoApplyGeometry) {
254            return false;
255        }
256
257        if (mDoApplyGeometry && !mGeoData.equals(preset.mGeoData)) {
258            return false;
259        }
260
261        if (mDoApplyGeometry && mBorder != preset.mBorder) {
262            return false;
263        }
264
265        if (mBorder != null && !mBorder.equals(preset.mBorder)) {
266            return false;
267        }
268
269        if (mDoApplyFilters != preset.mDoApplyFilters) {
270            if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
271                return false;
272            }
273        }
274
275        if (mDoApplyFilters && preset.mDoApplyFilters) {
276            for (int i = 0; i < preset.mFilters.size(); i++) {
277                FilterRepresentation a = preset.mFilters.elementAt(i);
278                FilterRepresentation b = mFilters.elementAt(i);
279                if (!a.same(b)) {
280                    return false;
281                }
282            }
283        }
284
285        return true;
286    }
287
288    public int similarUpTo(ImagePreset preset) {
289        if (!mGeoData.equals(preset.mGeoData)) {
290            return -1;
291        }
292
293        for (int i = 0; i < preset.mFilters.size(); i++) {
294            FilterRepresentation a = preset.mFilters.elementAt(i);
295            if (i < mFilters.size()) {
296                FilterRepresentation b = mFilters.elementAt(i);
297                if (!a.same(b)) {
298                    return i;
299                }
300                if (!a.equals(b)) {
301                    return i;
302                }
303            } else {
304                return i;
305            }
306        }
307        return preset.mFilters.size();
308    }
309
310    public String name() {
311        return mName;
312    }
313
314    public String historyName() {
315        return mHistoryName;
316    }
317
318    public void showFilters() {
319        Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters");
320        int n = 0;
321        for (FilterRepresentation representation : mFilters) {
322            Log.v(LOGTAG, " filter " + n + " : " + representation.toString());
323            n++;
324        }
325        Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters");
326    }
327
328    public void addFilter(FilterRepresentation representation) {
329        Log.v(LOGTAG, "*** Add Filter *** " + representation);
330        if (representation.getPriority() == FilterRepresentation.TYPE_BORDER) {
331            setHistoryName(representation.getName());
332            setBorder(representation);
333        } else if (representation.getPriority() == FilterRepresentation.TYPE_FX) {
334            boolean found = false;
335            for (int i = 0; i < mFilters.size(); i++) {
336                int type = mFilters.elementAt(i).getPriority();
337                if (found) {
338                    if (type != FilterRepresentation.TYPE_VIGNETTE) {
339                        mFilters.remove(i);
340                        continue;
341                    }
342                }
343                if (type == FilterRepresentation.TYPE_FX) {
344                    mFilters.remove(i);
345                    mFilters.add(i, representation);
346                    setHistoryName(representation.getName());
347                    found = true;
348                }
349            }
350            if (!found) {
351                mFilters.add(representation);
352                setHistoryName(representation.getName());
353            }
354        } else {
355            mFilters.add(representation);
356            setHistoryName(representation.getName());
357        }
358        representation.setImagePreset(this);
359    }
360
361    public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
362        for (int i = 0; i < mFilters.size(); i++) {
363            FilterRepresentation representation = mFilters.elementAt(i);
364            if (representation.getFilterClass() == filterRepresentation.getFilterClass()) {
365                return representation;
366            }
367        }
368        if (mBorder != null && mBorder.getFilterClass() == filterRepresentation.getFilterClass()) {
369            return mBorder;
370        }
371        return null;
372    }
373
374    public void setup() {
375        // do nothing here
376    }
377
378    public Bitmap apply(Bitmap original) {
379        Bitmap bitmap = original;
380        bitmap = applyFilters(bitmap, -1, -1);
381        return applyBorder(bitmap);
382    }
383
384    public Bitmap applyGeometry(Bitmap bitmap) {
385        // Apply any transform -- 90 rotate, flip, straighten, crop
386        // Returns a new bitmap.
387        return mGeoData.apply(bitmap, mScaleFactor, mQuality);
388    }
389
390    public Bitmap applyBorder(Bitmap bitmap) {
391        if (mBorder != null && mDoApplyGeometry) {
392            ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(mBorder);
393            filter.useRepresentation(mBorder);
394            bitmap = filter.apply(bitmap, mScaleFactor, mQuality);
395        }
396        return bitmap;
397    }
398
399    public Bitmap applyFilters(Bitmap bitmap, int from, int to) {
400
401        if (mDoApplyFilters) {
402            if (from < 0) {
403                from = 0;
404            }
405            if (to == -1) {
406                to = mFilters.size();
407            }
408            for (int i = from; i < to; i++) {
409                FilterRepresentation representation = null;
410                synchronized (mFilters) {
411                    representation = mFilters.elementAt(i);
412                }
413                ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(representation);
414                filter.useRepresentation(representation);
415                bitmap = filter.apply(bitmap, mScaleFactor, mQuality);
416            }
417        }
418
419        return bitmap;
420    }
421
422    public void fillImageStateAdapter(ImageStateAdapter imageStateAdapter) {
423        if (imageStateAdapter == null) {
424            return;
425        }
426        imageStateAdapter.clear();
427        // TODO: re-enable the state panel
428        imageStateAdapter.addAll(mFilters);
429        imageStateAdapter.notifyDataSetChanged();
430    }
431
432    public float getScaleFactor() {
433        return mScaleFactor;
434    }
435
436    public int getQuality() {
437        return mQuality;
438    }
439
440    public void setQuality(int value) {
441        mQuality = value;
442    }
443
444    public void setScaleFactor(float value) {
445        mScaleFactor = value;
446    }
447}
448