ImagePreset.java revision 19b307f5ef03b63493bd29e8e838a22c323a370a
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                addFilter(representation);
80            }
81        } catch (java.lang.CloneNotSupportedException e) {
82            Log.v(LOGTAG, "Exception trying to clone: " + e);
83        }
84        mName = source.name();
85        mHistoryName = source.name();
86        mIsFxPreset = source.isFx();
87        mImageLoader = source.getImageLoader();
88
89        mGeoData.set(source.mGeoData);
90    }
91
92    public FilterRepresentation getFilterRepresentation(int position) {
93        FilterRepresentation representation = null;
94        try {
95            representation = mFilters.elementAt(position).clone();
96        } catch (CloneNotSupportedException e) {
97            e.printStackTrace();
98        }
99        return representation;
100    }
101
102    public int getPositionForRepresentation(FilterRepresentation representation) {
103        for (int i = 0; i < mFilters.size(); i++) {
104            if (mFilters.elementAt(i).getFilterClass() == representation.getFilterClass()) {
105                return i;
106            }
107        }
108        return -1;
109    }
110
111    public FilterRepresentation getFilterRepresentationCopyFrom(FilterRepresentation filterRepresentation) {
112        // TODO: add concept of position in the filters (to allow multiple instances)
113        if (filterRepresentation == null) {
114            return null;
115        }
116        int position = getPositionForRepresentation(filterRepresentation);
117        if (position == -1) {
118            return null;
119        }
120        FilterRepresentation representation = null;
121        try {
122            representation = mFilters.elementAt(position).clone();
123        } catch (CloneNotSupportedException e) {
124            e.printStackTrace();
125        }
126        return representation;
127    }
128
129    public void updateFilterRepresentation(FilterRepresentation representation) {
130        synchronized (mFilters) {
131            int position = getPositionForRepresentation(representation);
132            FilterRepresentation old = mFilters.elementAt(position);
133            old.useParametersFrom(representation);
134        }
135        MasterImage.getImage().invalidatePreview();
136    }
137
138    public void setDoApplyGeometry(boolean value) {
139        mDoApplyGeometry = value;
140    }
141
142    public void setDoApplyFilters(boolean value) {
143        mDoApplyFilters = value;
144    }
145
146    public boolean getDoApplyFilters() {
147        return mDoApplyFilters;
148    }
149
150    public synchronized GeometryMetadata getGeometry() {
151        return mGeoData;
152    }
153
154    public boolean hasModifications() {
155        if (mBorder != null && !mBorder.isNil()) {
156            return true;
157        }
158        if (mGeoData.hasModifications()) {
159            return true;
160        }
161        for (int i = 0; i < mFilters.size(); i++) {
162            FilterRepresentation filter = mFilters.elementAt(i);
163            if (!filter.isNil()) {
164                return true;
165            }
166        }
167        return false;
168    }
169
170    public boolean isPanoramaSafe() {
171        if (mBorder != null && !mBorder.isNil()) {
172            return false;
173        }
174        if (mGeoData.hasModifications()) {
175            return false;
176        }
177        for (FilterRepresentation representation : mFilters) {
178            if (representation.getPriority() == FilterRepresentation.TYPE_VIGNETTE
179                && !representation.isNil()) {
180                return false;
181            }
182            if (representation.getPriority() == FilterRepresentation.TYPE_TINYPLANET
183                && !representation.isNil()) {
184                return false;
185            }
186        }
187        return true;
188    }
189
190    public synchronized void setGeometry(GeometryMetadata m) {
191        mGeoData.set(m);
192    }
193
194    private void setBorder(FilterRepresentation filter) {
195        mBorder = filter;
196    }
197
198    public boolean isFx() {
199        return mIsFxPreset;
200    }
201
202    public void setIsFx(boolean value) {
203        mIsFxPreset = value;
204    }
205
206    public void setName(String name) {
207        mName = name;
208        mHistoryName = name;
209    }
210
211    public void setHistoryName(String name) {
212        mHistoryName = name;
213    }
214
215    public ImageLoader getImageLoader() {
216        return mImageLoader;
217    }
218
219    public void setImageLoader(ImageLoader mImageLoader) {
220        this.mImageLoader = mImageLoader;
221    }
222
223    public boolean equals(ImagePreset preset) {
224        if (!same(preset)) {
225            return false;
226        }
227        if (mDoApplyFilters && preset.mDoApplyFilters) {
228            for (int i = 0; i < preset.mFilters.size(); i++) {
229                FilterRepresentation a = preset.mFilters.elementAt(i);
230                FilterRepresentation b = mFilters.elementAt(i);
231                if (!a.equals(b)) {
232                    return false;
233                }
234            }
235        }
236        return true;
237    }
238
239    public boolean same(ImagePreset preset) {
240        if (preset == null) {
241            return false;
242        }
243
244        if (preset.mFilters.size() != mFilters.size()) {
245            return false;
246        }
247
248        if (!mName.equalsIgnoreCase(preset.name())) {
249            return false;
250        }
251
252        if (mDoApplyGeometry != preset.mDoApplyGeometry) {
253            return false;
254        }
255
256        if (mDoApplyGeometry && !mGeoData.equals(preset.mGeoData)) {
257            return false;
258        }
259
260        if (mDoApplyGeometry && mBorder != preset.mBorder) {
261            return false;
262        }
263
264        if (mBorder != null && !mBorder.equals(preset.mBorder)) {
265            return false;
266        }
267
268        if (mDoApplyFilters != preset.mDoApplyFilters) {
269            if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
270                return false;
271            }
272        }
273
274        if (mDoApplyFilters && preset.mDoApplyFilters) {
275            for (int i = 0; i < preset.mFilters.size(); i++) {
276                FilterRepresentation a = preset.mFilters.elementAt(i);
277                FilterRepresentation b = mFilters.elementAt(i);
278                if (!a.same(b)) {
279                    return false;
280                }
281            }
282        }
283
284        return true;
285    }
286
287    public int similarUpTo(ImagePreset preset) {
288        if (!mGeoData.equals(preset.mGeoData)) {
289            return -1;
290        }
291
292        for (int i = 0; i < preset.mFilters.size(); i++) {
293            FilterRepresentation a = preset.mFilters.elementAt(i);
294            if (i < mFilters.size()) {
295                FilterRepresentation b = mFilters.elementAt(i);
296                if (!a.same(b)) {
297                    return i;
298                }
299                if (!a.equals(b)) {
300                    return i;
301                }
302            } else {
303                return i;
304            }
305        }
306        return preset.mFilters.size();
307    }
308
309    public String name() {
310        return mName;
311    }
312
313    public String historyName() {
314        return mHistoryName;
315    }
316
317    public void showFilters() {
318        Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters");
319        int n = 0;
320        for (FilterRepresentation representation : mFilters) {
321            Log.v(LOGTAG, " filter " + n + " : " + representation.toString());
322            n++;
323        }
324        Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters");
325    }
326
327    public void addFilter(FilterRepresentation representation) {
328        Log.v(LOGTAG, "*** Add Filter *** " + representation);
329        if (representation.getPriority() == FilterRepresentation.TYPE_BORDER) {
330            setHistoryName(representation.getName());
331            setBorder(representation);
332        } else if (representation.getPriority() == FilterRepresentation.TYPE_FX) {
333            boolean found = false;
334            for (int i = 0; i < mFilters.size(); i++) {
335                int type = mFilters.elementAt(i).getPriority();
336                if (found) {
337                    if (type != FilterRepresentation.TYPE_VIGNETTE) {
338                        mFilters.remove(i);
339                        continue;
340                    }
341                }
342                if (type == FilterRepresentation.TYPE_FX) {
343                    mFilters.remove(i);
344                    mFilters.add(i, representation);
345                    setHistoryName(representation.getName());
346                    found = true;
347                }
348            }
349            if (!found) {
350                mFilters.add(representation);
351                setHistoryName(representation.getName());
352            }
353        } else {
354            mFilters.add(representation);
355            setHistoryName(representation.getName());
356        }
357    }
358
359    public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
360        for (int i = 0; i < mFilters.size(); i++) {
361            FilterRepresentation representation = mFilters.elementAt(i);
362            if (representation.getFilterClass() == filterRepresentation.getFilterClass()) {
363                return representation;
364            }
365        }
366        if (mBorder != null && mBorder.getFilterClass() == filterRepresentation.getFilterClass()) {
367            return mBorder;
368        }
369        return null;
370    }
371
372    public void setup() {
373        // do nothing here
374    }
375
376    public Bitmap apply(Bitmap original) {
377        Bitmap bitmap = original;
378        bitmap = applyFilters(bitmap, -1, -1);
379        return applyBorder(bitmap);
380    }
381
382    public Bitmap applyGeometry(Bitmap bitmap) {
383        // Apply any transform -- 90 rotate, flip, straighten, crop
384        // Returns a new bitmap.
385        return mGeoData.apply(bitmap, mScaleFactor, mQuality);
386    }
387
388    public Bitmap applyBorder(Bitmap bitmap) {
389        if (mBorder != null && mDoApplyGeometry) {
390            ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(mBorder);
391            filter.useRepresentation(mBorder);
392            filter.setImagePreset(this);
393            bitmap = filter.apply(bitmap, mScaleFactor, mQuality);
394        }
395        return bitmap;
396    }
397
398    public Bitmap applyFilters(Bitmap bitmap, int from, int to) {
399
400        if (mDoApplyFilters) {
401            if (from < 0) {
402                from = 0;
403            }
404            if (to == -1) {
405                to = mFilters.size();
406            }
407            for (int i = from; i < to; i++) {
408                FilterRepresentation representation = null;
409                synchronized (mFilters) {
410                    representation = mFilters.elementAt(i);
411                }
412                ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(representation);
413                filter.useRepresentation(representation);
414                bitmap = filter.apply(bitmap, mScaleFactor, mQuality);
415            }
416        }
417
418        return bitmap;
419    }
420
421    public void fillImageStateAdapter(ImageStateAdapter imageStateAdapter) {
422        if (imageStateAdapter == null) {
423            return;
424        }
425        imageStateAdapter.clear();
426        // TODO: re-enable the state panel
427        imageStateAdapter.addAll(mFilters);
428        imageStateAdapter.notifyDataSetChanged();
429    }
430
431    public float getScaleFactor() {
432        return mScaleFactor;
433    }
434
435    public int getQuality() {
436        return mQuality;
437    }
438
439    public void setQuality(int value) {
440        mQuality = value;
441    }
442
443    public void setScaleFactor(float value) {
444        mScaleFactor = value;
445    }
446}
447