summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java')
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java700
1 files changed, 700 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
new file mode 100644
index 000000000..c78bc1ef4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow.pipeline;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.support.v8.renderscript.Allocation;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
+import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.state.State;
+import com.android.gallery3d.filtershow.state.StateAdapter;
+import com.android.gallery3d.util.UsageStatistics;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Vector;
+
+public class ImagePreset {
+
+ private static final String LOGTAG = "ImagePreset";
+
+ private ImageLoader mImageLoader = null;
+
+ private Vector<FilterRepresentation> mFilters = new Vector<FilterRepresentation>();
+
+ protected boolean mIsFxPreset = false;
+
+ private boolean mDoApplyGeometry = true;
+ private boolean mDoApplyFilters = true;
+
+ private boolean mPartialRendering = false;
+ private Rect mPartialRenderingBounds;
+ private static final boolean DEBUG = true;
+
+ public ImagePreset() {
+ }
+
+ public ImagePreset(ImagePreset source) {
+ try {
+ for (int i = 0; i < source.mFilters.size(); i++) {
+ FilterRepresentation representation = null;
+ FilterRepresentation sourceRepresentation = source.mFilters.elementAt(i);
+ if (sourceRepresentation instanceof GeometryMetadata) {
+ GeometryMetadata geoData = new GeometryMetadata();
+ GeometryMetadata srcGeo = (GeometryMetadata) sourceRepresentation;
+ geoData.set(srcGeo);
+ representation = geoData;
+ } else {
+ // TODO: get rid of clone()...
+ representation = sourceRepresentation.clone();
+ }
+ addFilter(representation);
+ }
+ } catch (java.lang.CloneNotSupportedException e) {
+ Log.v(LOGTAG, "Exception trying to clone: " + e);
+ }
+ mImageLoader = source.getImageLoader();
+ }
+
+ public FilterRepresentation getFilterRepresentation(int position) {
+ FilterRepresentation representation = null;
+ try {
+ representation = mFilters.elementAt(position).clone();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ return representation;
+ }
+
+ public int getPositionForRepresentation(FilterRepresentation representation) {
+ for (int i = 0; i < mFilters.size(); i++) {
+ if (mFilters.elementAt(i).getFilterClass() == representation.getFilterClass()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private FilterRepresentation getFilterRepresentationForType(int type) {
+ for (int i = 0; i < mFilters.size(); i++) {
+ if (mFilters.elementAt(i).getFilterType() == type) {
+ return mFilters.elementAt(i);
+ }
+ }
+ return null;
+ }
+
+ public int getPositionForType(int type) {
+ for (int i = 0; i < mFilters.size(); i++) {
+ if (mFilters.elementAt(i).getFilterType() == type) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public FilterRepresentation getFilterRepresentationCopyFrom(FilterRepresentation filterRepresentation) {
+ // TODO: add concept of position in the filters (to allow multiple instances)
+ if (filterRepresentation == null) {
+ return null;
+ }
+ int position = getPositionForRepresentation(filterRepresentation);
+ if (position == -1) {
+ return null;
+ }
+ FilterRepresentation representation = mFilters.elementAt(position);
+ if (representation != null) {
+ try {
+ representation = representation.clone();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ }
+ return representation;
+ }
+
+ public void updateFilterRepresentation(FilterRepresentation representation) {
+ if (representation == null) {
+ return;
+ }
+ if (representation instanceof GeometryMetadata) {
+ setGeometry((GeometryMetadata) representation);
+ } else {
+ int position = getPositionForRepresentation(representation);
+ if (position == -1) {
+ return;
+ }
+ FilterRepresentation old = mFilters.elementAt(position);
+ old.useParametersFrom(representation);
+ }
+ MasterImage.getImage().invalidatePreview();
+ fillImageStateAdapter(MasterImage.getImage().getState());
+ }
+
+ public void setDoApplyGeometry(boolean value) {
+ mDoApplyGeometry = value;
+ }
+
+ public void setDoApplyFilters(boolean value) {
+ mDoApplyFilters = value;
+ }
+
+ public boolean getDoApplyFilters() {
+ return mDoApplyFilters;
+ }
+
+ public GeometryMetadata getGeometry() {
+ for (FilterRepresentation representation : mFilters) {
+ if (representation instanceof GeometryMetadata) {
+ return (GeometryMetadata) representation;
+ }
+ }
+ GeometryMetadata geo = new GeometryMetadata();
+ mFilters.add(0, geo); // Hard Requirement for now -- Geometry ought to be first.
+ return geo;
+ }
+
+ public boolean hasModifications() {
+ for (int i = 0; i < mFilters.size(); i++) {
+ FilterRepresentation filter = mFilters.elementAt(i);
+ if (filter instanceof GeometryMetadata) {
+ if (((GeometryMetadata) filter).hasModifications()) {
+ return true;
+ }
+ } else if (!filter.isNil()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isPanoramaSafe() {
+ for (FilterRepresentation representation : mFilters) {
+ if (representation instanceof GeometryMetadata) {
+ if (((GeometryMetadata) representation).hasModifications()) {
+ return false;
+ }
+ }
+ if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER
+ && !representation.isNil()) {
+ return false;
+ }
+ if (representation.getFilterType() == FilterRepresentation.TYPE_VIGNETTE
+ && !representation.isNil()) {
+ return false;
+ }
+ if (representation.getFilterType() == FilterRepresentation.TYPE_TINYPLANET
+ && !representation.isNil()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void setGeometry(GeometryMetadata representation) {
+ GeometryMetadata geoData = getGeometry();
+ if (geoData != representation) {
+ geoData.set(representation);
+ }
+ }
+
+ public ImageLoader getImageLoader() {
+ return mImageLoader;
+ }
+
+ public void setImageLoader(ImageLoader mImageLoader) {
+ this.mImageLoader = mImageLoader;
+ }
+
+ public boolean equals(ImagePreset preset) {
+ if (!same(preset)) {
+ return false;
+ }
+ if (mDoApplyFilters && preset.mDoApplyFilters) {
+ for (int i = 0; i < preset.mFilters.size(); i++) {
+ FilterRepresentation a = preset.mFilters.elementAt(i);
+ FilterRepresentation b = mFilters.elementAt(i);
+ if (!a.equals(b)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean same(ImagePreset preset) {
+ if (preset == null) {
+ return false;
+ }
+
+ if (preset.mFilters.size() != mFilters.size()) {
+ return false;
+ }
+
+ if (mDoApplyGeometry != preset.mDoApplyGeometry) {
+ return false;
+ }
+
+ if (mDoApplyGeometry && !getGeometry().equals(preset.getGeometry())) {
+ return false;
+ }
+
+ if (mDoApplyFilters != preset.mDoApplyFilters) {
+ if (mFilters.size() > 0 || preset.mFilters.size() > 0) {
+ return false;
+ }
+ }
+
+ if (mDoApplyFilters && preset.mDoApplyFilters) {
+ for (int i = 0; i < preset.mFilters.size(); i++) {
+ FilterRepresentation a = preset.mFilters.elementAt(i);
+ FilterRepresentation b = mFilters.elementAt(i);
+ if (a instanceof GeometryMetadata) {
+ // Note: Geometry will always be at the same place
+ continue;
+ }
+ if (!a.same(b)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public int similarUpTo(ImagePreset preset) {
+ if (!getGeometry().equals(preset.getGeometry())) {
+ return -1;
+ }
+
+ for (int i = 0; i < preset.mFilters.size(); i++) {
+ FilterRepresentation a = preset.mFilters.elementAt(i);
+ if (i < mFilters.size()) {
+ FilterRepresentation b = mFilters.elementAt(i);
+ if (!a.same(b)) {
+ return i;
+ }
+ if (!a.equals(b)) {
+ return i;
+ }
+ } else {
+ return i;
+ }
+ }
+ return preset.mFilters.size();
+ }
+
+ public void showFilters() {
+ Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters");
+ int n = 0;
+ for (FilterRepresentation representation : mFilters) {
+ Log.v(LOGTAG, " filter " + n + " : " + representation.toString());
+ n++;
+ }
+ Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters");
+ }
+
+ public FilterRepresentation getLastRepresentation() {
+ if (mFilters.size() > 0) {
+ return mFilters.lastElement();
+ }
+ return null;
+ }
+
+ public void removeFilter(FilterRepresentation filterRepresentation) {
+ if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
+ for (int i = 0; i < mFilters.size();i++) {
+ if (mFilters.elementAt(i).getFilterType()
+ == filterRepresentation.getFilterType()) {
+ mFilters.remove(i);
+ break;
+ }
+ }
+ } else {
+ for (int i = 0; i < mFilters.size(); i++) {
+ if (mFilters.elementAt(i).getFilterClass()
+ == filterRepresentation.getFilterClass()) {
+ mFilters.remove(i);
+ break;
+ }
+ }
+ }
+ }
+
+ // If the filter is an "None" effect or border, then just don't add this
+ // filter.
+ public void addFilter(FilterRepresentation representation) {
+ if (representation instanceof GeometryMetadata) {
+ setGeometry((GeometryMetadata) representation);
+ return;
+ }
+
+ if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
+ removeFilter(representation);
+ if (!isNoneBorderFilter(representation)) {
+ mFilters.add(representation);
+ }
+ } else if (representation.getFilterType() == FilterRepresentation.TYPE_FX) {
+ boolean found = false;
+ for (int i = 0; i < mFilters.size(); i++) {
+ int type = mFilters.elementAt(i).getFilterType();
+ if (found) {
+ if (type != FilterRepresentation.TYPE_VIGNETTE) {
+ mFilters.remove(i);
+ continue;
+ }
+ }
+ if (type == FilterRepresentation.TYPE_FX) {
+ mFilters.remove(i);
+ if (!isNoneFxFilter(representation)) {
+ mFilters.add(i, representation);
+ }
+ found = true;
+ }
+ }
+ if (!found) {
+ if (!isNoneFxFilter(representation)) {
+ mFilters.add(representation);
+ }
+ }
+ } else {
+ mFilters.add(representation);
+ }
+ }
+
+ private boolean isNoneBorderFilter(FilterRepresentation representation) {
+ return representation instanceof FilterImageBorderRepresentation &&
+ ((FilterImageBorderRepresentation) representation).getDrawableResource() == 0;
+ }
+
+ private boolean isNoneFxFilter(FilterRepresentation representation) {
+ return representation instanceof FilterFxRepresentation &&
+ ((FilterFxRepresentation)representation).getNameResource() == R.string.none;
+ }
+
+ public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
+ for (int i = 0; i < mFilters.size(); i++) {
+ FilterRepresentation representation = mFilters.elementAt(i);
+ if (representation.getFilterClass() == filterRepresentation.getFilterClass()) {
+ return representation;
+ }
+ }
+ return null;
+ }
+
+ public Bitmap apply(Bitmap original, FilterEnvironment environment) {
+ Bitmap bitmap = original;
+ bitmap = applyFilters(bitmap, -1, -1, environment);
+ return applyBorder(bitmap, environment);
+ }
+
+ public Bitmap applyGeometry(Bitmap bitmap, FilterEnvironment environment) {
+ // Apply any transform -- 90 rotate, flip, straighten, crop
+ // Returns a new bitmap.
+ if (mDoApplyGeometry) {
+ GeometryMetadata geoData = getGeometry();
+ bitmap = environment.applyRepresentation(geoData, bitmap);
+ }
+ return bitmap;
+ }
+
+ public Bitmap applyBorder(Bitmap bitmap, FilterEnvironment environment) {
+ // get the border from the list of filters.
+ FilterRepresentation border = getFilterRepresentationForType(
+ FilterRepresentation.TYPE_BORDER);
+ if (border != null && mDoApplyGeometry) {
+ bitmap = environment.applyRepresentation(border, bitmap);
+ if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ "SaveBorder", border.getSerializationName(), 1);
+ }
+ }
+ return bitmap;
+ }
+
+ public int nbFilters() {
+ return mFilters.size();
+ }
+
+ public Bitmap applyFilters(Bitmap bitmap, int from, int to, FilterEnvironment environment) {
+ if (mDoApplyFilters) {
+ if (from < 0) {
+ from = 0;
+ }
+ if (to == -1) {
+ to = mFilters.size();
+ }
+ if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ "SaveFilters", "Total", to - from + 1);
+ }
+ for (int i = from; i < to; i++) {
+ FilterRepresentation representation = mFilters.elementAt(i);
+ if (representation instanceof GeometryMetadata) {
+ // skip the geometry as it's already applied.
+ continue;
+ }
+ if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
+ // for now, let's skip the border as it will be applied in applyBorder()
+ // TODO: might be worth getting rid of applyBorder.
+ continue;
+ }
+ bitmap = environment.applyRepresentation(representation, bitmap);
+ if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) {
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ "SaveFilter", representation.getSerializationName(), 1);
+ }
+ if (environment.needsStop()) {
+ return bitmap;
+ }
+ }
+ }
+
+ return bitmap;
+ }
+
+ public void applyBorder(Allocation in, Allocation out,
+ boolean copyOut, FilterEnvironment environment) {
+ FilterRepresentation border = getFilterRepresentationForType(
+ FilterRepresentation.TYPE_BORDER);
+ if (border != null && mDoApplyGeometry) {
+ // TODO: should keep the bitmap around
+ Allocation bitmapIn = in;
+ if (copyOut) {
+ bitmapIn = Allocation.createTyped(
+ CachingPipeline.getRenderScriptContext(), in.getType());
+ bitmapIn.copyFrom(out);
+ }
+ environment.applyRepresentation(border, bitmapIn, out);
+ }
+ }
+
+ public void applyFilters(int from, int to, Allocation in, Allocation out,
+ FilterEnvironment environment) {
+ if (mDoApplyFilters) {
+ if (from < 0) {
+ from = 0;
+ }
+ if (to == -1) {
+ to = mFilters.size();
+ }
+ for (int i = from; i < to; i++) {
+ FilterRepresentation representation = mFilters.elementAt(i);
+ if (representation instanceof GeometryMetadata) {
+ // skip the geometry as it's already applied.
+ continue;
+ }
+ if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
+ // for now, let's skip the border as it will be applied in applyBorder()
+ continue;
+ }
+ if (i > from) {
+ in.copyFrom(out);
+ }
+ environment.applyRepresentation(representation, in, out);
+ }
+ }
+ }
+
+ public boolean canDoPartialRendering() {
+ if (ImageLoader.getZoomOrientation() != ImageLoader.ORI_NORMAL) {
+ return false;
+ }
+ for (int i = 0; i < mFilters.size(); i++) {
+ FilterRepresentation representation = mFilters.elementAt(i);
+ if (representation instanceof GeometryMetadata
+ && ((GeometryMetadata) representation).hasModifications()) {
+ return false;
+ }
+ if (!representation.supportsPartialRendering()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void fillImageStateAdapter(StateAdapter imageStateAdapter) {
+ if (imageStateAdapter == null) {
+ return;
+ }
+ Vector<State> states = new Vector<State>();
+ for (FilterRepresentation filter : mFilters) {
+ if (filter instanceof GeometryMetadata) {
+ // TODO: supports Geometry representations in the state panel.
+ continue;
+ }
+ State state = new State(filter.getName());
+ state.setFilterRepresentation(filter);
+ states.add(state);
+ }
+ imageStateAdapter.fill(states);
+ }
+
+ public void setPartialRendering(boolean partialRendering, Rect bounds) {
+ mPartialRendering = partialRendering;
+ mPartialRenderingBounds = bounds;
+ }
+
+ public boolean isPartialRendering() {
+ return mPartialRendering;
+ }
+
+ public Rect getPartialRenderingBounds() {
+ return mPartialRenderingBounds;
+ }
+
+ public Vector<ImageFilter> getUsedFilters(BaseFiltersManager filtersManager) {
+ Vector<ImageFilter> usedFilters = new Vector<ImageFilter>();
+ for (int i = 0; i < mFilters.size(); i++) {
+ FilterRepresentation representation = mFilters.elementAt(i);
+ ImageFilter filter = filtersManager.getFilterForRepresentation(representation);
+ usedFilters.add(filter);
+ }
+ return usedFilters;
+ }
+
+ public String getJsonString(String name) {
+ StringWriter swriter = new StringWriter();
+ try {
+ JsonWriter writer = new JsonWriter(swriter);
+ writeJson(writer, name);
+ writer.close();
+ } catch (IOException e) {
+ return null;
+ }
+ return swriter.toString();
+ }
+
+ public void writeJson(JsonWriter writer, String name) {
+ int numFilters = mFilters.size();
+ try {
+ writer.beginObject();
+ GeometryMetadata geoData = getGeometry();
+ writer.name(geoData.getSerializationName());
+ writer.beginObject();
+ {
+ String[][] rep = geoData.serializeRepresentation();
+ for (int i = 0; i < rep.length; i++) {
+ writer.name(rep[i][0]);
+ writer.value(rep[i][1]);
+ }
+ }
+ writer.endObject();
+
+ for (int i = 0; i < numFilters; i++) {
+ FilterRepresentation filter = mFilters.get(i);
+ if (filter instanceof GeometryMetadata) {
+ continue;
+ }
+ String sname = filter.getSerializationName();
+ if (DEBUG) {
+ Log.v(LOGTAG, "Serialization: " + sname);
+ if (sname == null) {
+ Log.v(LOGTAG, "Serialization: " + filter);
+ }
+ }
+ writer.name(sname);
+ filter.serializeRepresentation(writer);
+ }
+ writer.endObject();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * populates preset from JSON string
+ * @param filterString a JSON string
+ * @return true on success if false ImagePreset is undefined
+ */
+ public boolean readJsonFromString(String filterString) {
+ if (DEBUG) {
+ Log.v(LOGTAG,"reading preset: \""+filterString+"\"");
+ }
+ StringReader sreader = new StringReader(filterString);
+ try {
+ JsonReader reader = new JsonReader(sreader);
+ boolean ok = readJson(reader);
+ if (!ok) {
+ reader.close();
+ return false;
+ }
+ reader.close();
+ } catch (Exception e) {
+ Log.e(LOGTAG,"parsing the filter parameters:",e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * populates preset from JSON stream
+ * @param sreader a JSON string
+ * @return true on success if false ImagePreset is undefined
+ */
+ public boolean readJson(JsonReader sreader) throws IOException {
+ sreader.beginObject();
+
+ while (sreader.hasNext()) {
+ String name = sreader.nextName();
+ FilterRepresentation filter = creatFilterFromName(name);
+ if (filter == null) {
+ Log.w(LOGTAG,"UNKNOWN FILTER! "+name);
+ return false;
+ }
+ filter.deSerializeRepresentation(sreader);
+ addFilter(filter);
+ }
+ sreader.endObject();
+ return true;
+ }
+
+ FilterRepresentation creatFilterFromName(String name) {
+ if (GeometryMetadata.SERIALIZATION_NAME.equalsIgnoreCase(name)) {
+ return new GeometryMetadata();
+ }
+ FiltersManager filtersManager = FiltersManager.getManager();
+ return filtersManager.createFilterFromName(name);
+ }
+
+ public void updateWith(ImagePreset preset) {
+ if (preset.mFilters.size() != mFilters.size()) {
+ Log.e(LOGTAG, "Updating a preset with an incompatible one");
+ return;
+ }
+ for (int i = 0; i < mFilters.size(); i++) {
+ FilterRepresentation destRepresentation = mFilters.elementAt(i);
+ FilterRepresentation sourceRepresentation = preset.mFilters.elementAt(i);
+ destRepresentation.useParametersFrom(sourceRepresentation);
+ }
+ }
+}