1/*
2 * Copyright (C) 2013 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 */
16package com.android.gallery3d.filtershow.filters;
17
18import android.content.Context;
19import android.content.res.Resources;
20import android.graphics.Color;
21import android.util.Log;
22
23import com.android.gallery3d.R;
24import com.android.gallery3d.filtershow.pipeline.ImagePreset;
25
26import java.util.ArrayList;
27import java.util.HashMap;
28import java.util.Vector;
29
30public abstract class BaseFiltersManager implements FiltersManagerInterface {
31    protected HashMap<Class, ImageFilter> mFilters = null;
32    protected HashMap<String, FilterRepresentation> mRepresentationLookup = null;
33    private static final String LOGTAG = "BaseFiltersManager";
34
35    protected ArrayList<FilterRepresentation> mLooks = new ArrayList<FilterRepresentation>();
36    protected ArrayList<FilterRepresentation> mBorders = new ArrayList<FilterRepresentation>();
37    protected ArrayList<FilterRepresentation> mTools = new ArrayList<FilterRepresentation>();
38    protected ArrayList<FilterRepresentation> mEffects = new ArrayList<FilterRepresentation>();
39    private static int mImageBorderSize = 4; // in percent
40
41    protected void init() {
42        mFilters = new HashMap<Class, ImageFilter>();
43        mRepresentationLookup = new HashMap<String, FilterRepresentation>();
44        Vector<Class> filters = new Vector<Class>();
45        addFilterClasses(filters);
46        for (Class filterClass : filters) {
47            try {
48                Object filterInstance = filterClass.newInstance();
49                if (filterInstance instanceof ImageFilter) {
50                    mFilters.put(filterClass, (ImageFilter) filterInstance);
51
52                    FilterRepresentation rep =
53                        ((ImageFilter) filterInstance).getDefaultRepresentation();
54                    if (rep != null) {
55                        addRepresentation(rep);
56                    }
57                }
58            } catch (InstantiationException e) {
59                e.printStackTrace();
60            } catch (IllegalAccessException e) {
61                e.printStackTrace();
62            }
63        }
64    }
65
66    public void addRepresentation(FilterRepresentation rep) {
67        mRepresentationLookup.put(rep.getSerializationName(), rep);
68    }
69
70    public FilterRepresentation createFilterFromName(String name) {
71        try {
72            return mRepresentationLookup.get(name).copy();
73        } catch (Exception e) {
74            Log.v(LOGTAG, "unable to generate a filter representation for \"" + name + "\"");
75            e.printStackTrace();
76        }
77        return null;
78    }
79
80    public ImageFilter getFilter(Class c) {
81        return mFilters.get(c);
82    }
83
84    @Override
85    public ImageFilter getFilterForRepresentation(FilterRepresentation representation) {
86        return mFilters.get(representation.getFilterClass());
87    }
88
89    public FilterRepresentation getRepresentation(Class c) {
90        ImageFilter filter = mFilters.get(c);
91        if (filter != null) {
92            return filter.getDefaultRepresentation();
93        }
94        return null;
95    }
96
97    public void freeFilterResources(ImagePreset preset) {
98        if (preset == null) {
99            return;
100        }
101        Vector<ImageFilter> usedFilters = preset.getUsedFilters(this);
102        for (Class c : mFilters.keySet()) {
103            ImageFilter filter = mFilters.get(c);
104            if (!usedFilters.contains(filter)) {
105                filter.freeResources();
106            }
107        }
108    }
109
110    public void freeRSFilterScripts() {
111        for (Class c : mFilters.keySet()) {
112            ImageFilter filter = mFilters.get(c);
113            if (filter != null && filter instanceof ImageFilterRS) {
114                ((ImageFilterRS) filter).resetScripts();
115            }
116        }
117    }
118
119    protected void addFilterClasses(Vector<Class> filters) {
120        filters.add(ImageFilterTinyPlanet.class);
121        filters.add(ImageFilterRedEye.class);
122        filters.add(ImageFilterWBalance.class);
123        filters.add(ImageFilterExposure.class);
124        filters.add(ImageFilterVignette.class);
125        filters.add(ImageFilterGrad.class);
126        filters.add(ImageFilterContrast.class);
127        filters.add(ImageFilterShadows.class);
128        filters.add(ImageFilterHighlights.class);
129        filters.add(ImageFilterVibrance.class);
130        filters.add(ImageFilterSharpen.class);
131        filters.add(ImageFilterCurves.class);
132        filters.add(ImageFilterDraw.class);
133        filters.add(ImageFilterHue.class);
134        filters.add(ImageFilterChanSat.class);
135        filters.add(ImageFilterSaturated.class);
136        filters.add(ImageFilterBwFilter.class);
137        filters.add(ImageFilterNegative.class);
138        filters.add(ImageFilterEdge.class);
139        filters.add(ImageFilterKMeans.class);
140        filters.add(ImageFilterFx.class);
141        filters.add(ImageFilterBorder.class);
142        filters.add(ImageFilterColorBorder.class);
143    }
144
145    public ArrayList<FilterRepresentation> getLooks() {
146        return mLooks;
147    }
148
149    public ArrayList<FilterRepresentation> getBorders() {
150        return mBorders;
151    }
152
153    public ArrayList<FilterRepresentation> getTools() {
154        return mTools;
155    }
156
157    public ArrayList<FilterRepresentation> getEffects() {
158        return mEffects;
159    }
160
161    public void addBorders(Context context) {
162
163        // Do not localize
164        String[] serializationNames = {
165                "FRAME_4X5",
166                "FRAME_BRUSH",
167                "FRAME_GRUNGE",
168                "FRAME_SUMI_E",
169                "FRAME_TAPE",
170                "FRAME_BLACK",
171                "FRAME_BLACK_ROUNDED",
172                "FRAME_WHITE",
173                "FRAME_WHITE_ROUNDED",
174                "FRAME_CREAM",
175                "FRAME_CREAM_ROUNDED"
176        };
177
178        // The "no border" implementation
179        int i = 0;
180        FilterRepresentation rep = new FilterImageBorderRepresentation(0);
181        mBorders.add(rep);
182
183        // Regular borders
184        ArrayList <FilterRepresentation> borderList = new ArrayList<FilterRepresentation>();
185
186
187        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_4x5);
188        borderList.add(rep);
189
190        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_brush);
191        borderList.add(rep);
192
193        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_grunge);
194        borderList.add(rep);
195
196        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_sumi_e);
197        borderList.add(rep);
198
199        rep = new FilterImageBorderRepresentation(R.drawable.filtershow_border_tape);
200        borderList.add(rep);
201
202        rep = new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, 0);
203        borderList.add(rep);
204
205        rep = new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize,
206                mImageBorderSize);
207        borderList.add(rep);
208
209        rep = new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, 0);
210        borderList.add(rep);
211
212        rep = new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize,
213                mImageBorderSize);
214        borderList.add(rep);
215
216        int creamColor = Color.argb(255, 237, 237, 227);
217        rep = new FilterColorBorderRepresentation(creamColor, mImageBorderSize, 0);
218        borderList.add(rep);
219
220        rep = new FilterColorBorderRepresentation(creamColor, mImageBorderSize,
221                mImageBorderSize);
222        borderList.add(rep);
223
224        for (FilterRepresentation filter : borderList) {
225            filter.setSerializationName(serializationNames[i++]);
226            addRepresentation(filter);
227            mBorders.add(filter);
228        }
229
230    }
231
232    public void addLooks(Context context) {
233        int[] drawid = {
234                R.drawable.filtershow_fx_0005_punch,
235                R.drawable.filtershow_fx_0000_vintage,
236                R.drawable.filtershow_fx_0004_bw_contrast,
237                R.drawable.filtershow_fx_0002_bleach,
238                R.drawable.filtershow_fx_0001_instant,
239                R.drawable.filtershow_fx_0007_washout,
240                R.drawable.filtershow_fx_0003_blue_crush,
241                R.drawable.filtershow_fx_0008_washout_color,
242                R.drawable.filtershow_fx_0006_x_process
243        };
244
245        int[] fxNameid = {
246                R.string.ffx_punch,
247                R.string.ffx_vintage,
248                R.string.ffx_bw_contrast,
249                R.string.ffx_bleach,
250                R.string.ffx_instant,
251                R.string.ffx_washout,
252                R.string.ffx_blue_crush,
253                R.string.ffx_washout_color,
254                R.string.ffx_x_process
255        };
256
257        // Do not localize.
258        String[] serializationNames = {
259                "LUT3D_PUNCH",
260                "LUT3D_VINTAGE",
261                "LUT3D_BW",
262                "LUT3D_BLEACH",
263                "LUT3D_INSTANT",
264                "LUT3D_WASHOUT",
265                "LUT3D_BLUECRUSH",
266                "LUT3D_WASHOUT_COLOR",
267                "LUT3D_XPROCESS"
268        };
269
270        FilterFxRepresentation nullFx =
271                new FilterFxRepresentation(context.getString(R.string.none),
272                        0, R.string.none);
273        mLooks.add(nullFx);
274
275        for (int i = 0; i < drawid.length; i++) {
276            FilterFxRepresentation fx = new FilterFxRepresentation(
277                    context.getString(fxNameid[i]), drawid[i], fxNameid[i]);
278            fx.setSerializationName(serializationNames[i]);
279            ImagePreset preset = new ImagePreset();
280            preset.addFilter(fx);
281            FilterUserPresetRepresentation rep = new FilterUserPresetRepresentation(
282                    context.getString(fxNameid[i]), preset, -1);
283            mLooks.add(rep);
284            addRepresentation(fx);
285        }
286    }
287
288    public void addEffects() {
289        mEffects.add(getRepresentation(ImageFilterTinyPlanet.class));
290        mEffects.add(getRepresentation(ImageFilterWBalance.class));
291        mEffects.add(getRepresentation(ImageFilterExposure.class));
292        mEffects.add(getRepresentation(ImageFilterVignette.class));
293        mEffects.add(getRepresentation(ImageFilterGrad.class));
294        mEffects.add(getRepresentation(ImageFilterContrast.class));
295        mEffects.add(getRepresentation(ImageFilterShadows.class));
296        mEffects.add(getRepresentation(ImageFilterHighlights.class));
297        mEffects.add(getRepresentation(ImageFilterVibrance.class));
298        mEffects.add(getRepresentation(ImageFilterSharpen.class));
299        mEffects.add(getRepresentation(ImageFilterCurves.class));
300        mEffects.add(getRepresentation(ImageFilterHue.class));
301        mEffects.add(getRepresentation(ImageFilterChanSat.class));
302        mEffects.add(getRepresentation(ImageFilterBwFilter.class));
303        mEffects.add(getRepresentation(ImageFilterNegative.class));
304        mEffects.add(getRepresentation(ImageFilterEdge.class));
305        mEffects.add(getRepresentation(ImageFilterKMeans.class));
306    }
307
308    public void addTools(Context context) {
309
310        int[] textId = {
311                R.string.crop,
312                R.string.straighten,
313                R.string.rotate,
314                R.string.mirror
315        };
316
317        int[] overlayId = {
318                R.drawable.filtershow_button_geometry_crop,
319                R.drawable.filtershow_button_geometry_straighten,
320                R.drawable.filtershow_button_geometry_rotate,
321                R.drawable.filtershow_button_geometry_flip
322        };
323
324        FilterRepresentation[] geometryFilters = {
325                new FilterCropRepresentation(),
326                new FilterStraightenRepresentation(),
327                new FilterRotateRepresentation(),
328                new FilterMirrorRepresentation()
329        };
330
331        for (int i = 0; i < textId.length; i++) {
332            FilterRepresentation geometry = geometryFilters[i];
333            geometry.setTextId(textId[i]);
334            geometry.setOverlayId(overlayId[i]);
335            geometry.setOverlayOnly(true);
336            if (geometry.getTextId() != 0) {
337                geometry.setName(context.getString(geometry.getTextId()));
338            }
339            mTools.add(geometry);
340        }
341
342        //mTools.add(getRepresentation(ImageFilterRedEye.class));
343        mTools.add(getRepresentation(ImageFilterDraw.class));
344    }
345
346    public void removeRepresentation(ArrayList<FilterRepresentation> list,
347                                          FilterRepresentation representation) {
348        for (int i = 0; i < list.size(); i++) {
349            FilterRepresentation r = list.get(i);
350            if (r.getFilterClass() == representation.getFilterClass()) {
351                list.remove(i);
352                break;
353            }
354        }
355    }
356
357    public void setFilterResources(Resources resources) {
358        ImageFilterBorder filterBorder = (ImageFilterBorder) getFilter(ImageFilterBorder.class);
359        filterBorder.setResources(resources);
360        ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class);
361        filterFx.setResources(resources);
362    }
363}
364