summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorByunghun Jeon <bjeon@codeaurora.org>2015-08-03 16:50:11 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2015-10-13 04:31:27 -0700
commit8ea62fb010059f600f0e26ad468ceab6bf0c8232 (patch)
treed622960b2312d56b98b99d5747064f8a54682e90 /src/com/android
parent8c969c5cf077a33082ea113f7421797ec1f89eb0 (diff)
downloadandroid_packages_apps_Gallery2-8ea62fb010059f600f0e26ad468ceab6bf0c8232.tar.gz
android_packages_apps_Gallery2-8ea62fb010059f600f0e26ad468ceab6bf0c8232.tar.bz2
android_packages_apps_Gallery2-8ea62fb010059f600f0e26ad468ceab6bf0c8232.zip
Gallery2: Add dual camera filters
Add dual camera based filters. CRs-Fixed: 892007 Change-Id: Ide26135ef8e83137f86abb96ca7ce29e94801bba
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java112
-rw-r--r--src/com/android/gallery3d/filtershow/cache/BitmapCache.java3
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryAdapter.java8
-rw-r--r--src/com/android/gallery3d/filtershow/category/CategoryPanel.java8
-rw-r--r--src/com/android/gallery3d/filtershow/category/MainPanel.java44
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java133
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java73
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java65
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorPanel.java4
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java71
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java149
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java185
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDualCamSketchRepresentation.java92
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java1
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java138
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java169
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java144
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java80
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java100
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java104
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/MasterImage.java143
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/Buffer.java3
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java2
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java89
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java3
-rw-r--r--src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java4
-rw-r--r--src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java103
-rw-r--r--src/com/android/gallery3d/filtershow/tools/SaveImage.java118
-rw-r--r--src/com/android/gallery3d/mpo/MpoHeader.java56
-rw-r--r--src/com/android/gallery3d/mpo/MpoParser.java291
30 files changed, 2361 insertions, 134 deletions
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 67fd3fe32..1b0318bc4 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -16,6 +16,11 @@
package com.android.gallery3d.filtershow;
+import java.io.File;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Vector;
+
import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -30,16 +35,13 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
-import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.DialogFragment;
@@ -63,7 +65,6 @@ import android.widget.FrameLayout;
import android.widget.PopupMenu;
import android.widget.ShareActionProvider;
import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
-import android.widget.Spinner;
import android.widget.Toast;
import com.android.gallery3d.R;
@@ -77,27 +78,15 @@ import com.android.gallery3d.filtershow.category.CategoryView;
import com.android.gallery3d.filtershow.category.MainPanel;
import com.android.gallery3d.filtershow.category.SwipableView;
import com.android.gallery3d.filtershow.data.UserPresetsManager;
-import com.android.gallery3d.filtershow.editors.BasicEditor;
import com.android.gallery3d.filtershow.editors.Editor;
-import com.android.gallery3d.filtershow.editors.EditorChanSat;
-import com.android.gallery3d.filtershow.editors.EditorColorBorder;
-import com.android.gallery3d.filtershow.editors.EditorCrop;
-import com.android.gallery3d.filtershow.editors.EditorDraw;
-import com.android.gallery3d.filtershow.editors.EditorGrad;
-import com.android.gallery3d.filtershow.editors.EditorMakeup;
+import com.android.gallery3d.filtershow.editors.EditorDualCamFusion;
import com.android.gallery3d.filtershow.editors.EditorManager;
-import com.android.gallery3d.filtershow.editors.EditorMirror;
import com.android.gallery3d.filtershow.editors.EditorPanel;
-import com.android.gallery3d.filtershow.editors.EditorRedEye;
-import com.android.gallery3d.filtershow.editors.EditorRotate;
-import com.android.gallery3d.filtershow.editors.EditorStraighten;
-import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -115,6 +104,7 @@ import com.android.gallery3d.filtershow.presets.PresetManagementDialog;
import com.android.gallery3d.filtershow.presets.UserPresetsAdapter;
import com.android.gallery3d.filtershow.provider.SharedImageProvider;
import com.android.gallery3d.filtershow.state.StateAdapter;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
import com.android.gallery3d.filtershow.tools.SaveImage;
import com.android.gallery3d.filtershow.tools.XmpPresets;
import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
@@ -124,13 +114,6 @@ import com.android.gallery3d.util.GalleryUtils;
import com.android.photos.data.GalleryBitmapPool;
import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Vector;
-
public class FilterShowActivity extends FragmentActivity implements OnItemClickListener,
OnShareTargetSelectedListener, DialogInterface.OnShowListener,
DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
@@ -151,6 +134,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
private Editor mCurrentEditor = null;
private static final int SELECT_PICTURE = 1;
+ public static final int SELECT_FUSION_UNDERLAY = 2;
private static final String LOGTAG = "FilterShowActivity";
private boolean mShowingTinyPlanet = false;
@@ -182,6 +166,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
private CategoryAdapter mCategoryFiltersAdapter = null;
private CategoryAdapter mCategoryVersionsAdapter = null;
private CategoryAdapter mCategoryMakeupAdapter = null;
+ private CategoryAdapter mCategoryDualCamAdapter = null;
private int mCurrentPanel = MainPanel.LOOKS;
private Vector<FilterUserPresetRepresentation> mVersions =
new Vector<FilterUserPresetRepresentation>();
@@ -264,7 +249,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
setupMasterImage();
setupMenu();
setDefaultValues();
- fillEditors();
getWindow().setBackgroundDrawable(new ColorDrawable(0));
loadXML();
@@ -385,6 +369,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
fillEffects();
fillVersions();
fillMakeup();
+ fillDualCamera();
}
public void setupStatePanel() {
@@ -492,6 +477,21 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
}
}
+ private void fillDualCamera() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getDualCamera();
+ if (mCategoryDualCamAdapter != null) {
+ mCategoryDualCamAdapter.clear();
+ }
+ mCategoryDualCamAdapter = new CategoryAdapter(this);
+ for (FilterRepresentation representation : filtersRepresentations) {
+ if (representation.getTextId() != 0) {
+ representation.setName(getString(representation.getTextId()));
+ }
+ mCategoryDualCamAdapter.add(new Action(this, representation));
+ }
+ }
+
private void fillTools() {
FiltersManager filtersManager = FiltersManager.getManager();
ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools();
@@ -530,7 +530,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
if (loadUri != null) {
startLoadBitmap(loadUri);
} else {
- pickImage();
+ pickImage(SELECT_PICTURE);
}
}
@@ -540,22 +540,6 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
mEditorPlaceHolder.setOldViews(mImageViews);
}
- private void fillEditors() {
- mEditorPlaceHolder.addEditor(new EditorChanSat());
- mEditorPlaceHolder.addEditor(new EditorGrad());
- mEditorPlaceHolder.addEditor(new EditorDraw());
- mEditorPlaceHolder.addEditor(new EditorColorBorder());
- mEditorPlaceHolder.addEditor(new BasicEditor());
- mEditorPlaceHolder.addEditor(new ImageOnlyEditor());
- mEditorPlaceHolder.addEditor(new EditorTinyPlanet());
- mEditorPlaceHolder.addEditor(new EditorRedEye());
- mEditorPlaceHolder.addEditor(new EditorCrop());
- mEditorPlaceHolder.addEditor(new EditorMirror());
- mEditorPlaceHolder.addEditor(new EditorRotate());
- mEditorPlaceHolder.addEditor(new EditorStraighten());
- mEditorPlaceHolder.addEditor(new EditorMakeup());
- }
-
private void setDefaultValues() {
Resources res = getResources();
@@ -624,6 +608,10 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
return mCategoryVersionsAdapter;
}
+ public CategoryAdapter getCategoryDualCamAdapter() {
+ return mCategoryDualCamAdapter;
+ }
+
public void removeFilterRepresentation(FilterRepresentation filterRepresentation) {
if (filterRepresentation == null) {
return;
@@ -729,6 +717,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
ImagePreset preset = mMasterImage.getPreset();
mCategoryLooksAdapter.reflectImagePreset(preset);
mCategoryBordersAdapter.reflectImagePreset(preset);
+ mCategoryDualCamAdapter.reflectImagePreset(preset);
}
public View getMainStatePanelContainer(int id) {
@@ -790,10 +779,33 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
Log.d(LOGTAG, "FilterShowActivity.LoadHighresBitmapTask.onPostExecute(): highResPreviewScale is " + highResPreviewScale);
mBoundService.setHighresPreviewScaleFactor(highResPreviewScale);
}
+
+ if(DualCameraNativeEngine.getInstance().isLibLoaded()) {
+ LoadMpoDataTask mpoLoad = new LoadMpoDataTask();
+ mpoLoad.execute();
+ }
MasterImage.getImage().warnListeners();
}
}
+ private class LoadMpoDataTask extends AsyncTask<Void, Void, Boolean> {
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ return MasterImage.getImage().loadMpo();
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ MasterImage.getImage().warnListeners();
+
+ Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ if (currentPanel instanceof MainPanel) {
+ MainPanel mainPanel = (MainPanel) currentPanel;
+ mainPanel.enableDualCameraButton(result);
+ }
+ }
+ }
+
public boolean isLoadingVisible() {
return mLoadingVisible;
}
@@ -881,6 +893,7 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
mCategoryBordersAdapter.imageLoaded();
mCategoryGeometryAdapter.imageLoaded();
mCategoryFiltersAdapter.imageLoaded();
+ mCategoryDualCamAdapter.imageLoaded();
if(mCategoryMakeupAdapter != null) {
mCategoryMakeupAdapter.imageLoaded();
}
@@ -929,6 +942,8 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
}
mUserPresetsManager.close();
doUnbindService();
+ if(DualCameraNativeEngine.getInstance().isLibLoaded())
+ DualCameraNativeEngine.getInstance().releaseDepthMap();
super.onDestroy();
}
@@ -1060,6 +1075,8 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
if(SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
MakeupEngine.getMakeupObj().setContext(getBaseContext());
}
+
+ DualCameraNativeEngine.createInstance();
}
@Override
@@ -1402,12 +1419,12 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
invalidateViews();
}
- public void pickImage() {
+ public void pickImage(int requestCode) {
Intent intent = new Intent();
intent.setType("image/*");
- intent.setAction(Intent.ACTION_GET_CONTENT);
+ intent.setAction(Intent.ACTION_PICK);
startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
- SELECT_PICTURE);
+ requestCode);
}
@Override
@@ -1416,6 +1433,11 @@ public class FilterShowActivity extends FragmentActivity implements OnItemClickL
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
startLoadBitmap(selectedImageUri);
+ } else if (requestCode == SELECT_FUSION_UNDERLAY) {
+ Uri underlayImageUri = data.getData();
+ // find fusion representation
+ EditorDualCamFusion editor = (EditorDualCamFusion)getEditor(EditorDualCamFusion.ID);
+ editor.setUnderlayImageUri(underlayImageUri);
}
}
}
diff --git a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
index cd63d309a..4c246a482 100644
--- a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
+++ b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
@@ -18,7 +18,9 @@ package com.android.gallery3d.filtershow.cache;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.PorterDuff;
import android.util.Log;
+
import com.android.gallery3d.filtershow.pipeline.Buffer;
import com.android.gallery3d.filtershow.pipeline.CacheProcessing;
@@ -206,6 +208,7 @@ public class BitmapCache {
public synchronized Bitmap getBitmapCopy(Bitmap source, int type) {
Bitmap bitmap = getBitmap(source.getWidth(), source.getHeight(), type);
Canvas canvas = new Canvas(bitmap);
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawBitmap(source, 0, 0, null);
return bitmap;
}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
index 50f0e9436..9571d8b16 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
@@ -85,6 +85,9 @@ public class CategoryAdapter extends ArrayAdapter<Action> {
if (category == MainPanel.BORDERS) {
mSelectedPosition = 0;
}
+ if (category == MainPanel.DUALCAM) {
+ mSelectedPosition = 0;
+ }
if (category == MainPanel.VERSIONS) {
mAddButtonText = getContext().getString(R.string.filtershow_add_button_versions);
}
@@ -213,6 +216,11 @@ public class CategoryAdapter extends ArrayAdapter<Action> {
if (pos != -1) {
rep = preset.getFilterRepresentation(pos);
}
+ } else if (mCategory == MainPanel.DUALCAM) {
+ int pos = preset.getPositionForType(FilterRepresentation.TYPE_DUALCAM);
+ if (pos != -1) {
+ rep = preset.getFilterRepresentation(pos);
+ }
}
if (rep != null) {
for (int i = 0; i < getCount(); i++) {
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
index 66b352ffb..3ee9e45eb 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
@@ -82,6 +82,14 @@ public class CategoryPanel extends Fragment implements View.OnClickListener {
}
break;
}
+ case MainPanel.DUALCAM: {
+ mAdapter = activity.getCategoryDualCamAdapter();
+ if (mAdapter != null) {
+ mAdapter.initializeSelection(MainPanel.DUALCAM);
+ }
+ activity.updateCategories();
+ break;
+ }
case MainPanel.VERSIONS: {
mAdapter = activity.getCategoryVersionsAdapter();
if (mAdapter != null) {
diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java
index 1dbe42083..a80df3bfa 100644
--- a/src/com/android/gallery3d/filtershow/category/MainPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/MainPanel.java
@@ -24,12 +24,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
-import android.util.Log;
+
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.filters.SimpleMakeupImageFilter;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.state.StatePanel;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
public class MainPanel extends Fragment {
@@ -40,6 +41,7 @@ public class MainPanel extends Fragment {
private ImageButton bordersButton;
private ImageButton geometryButton;
private ImageButton filtersButton;
+ private ImageButton dualCamButton;
private ImageButton makeupButton;
public static final String FRAGMENT_TAG = "MainPanel";
@@ -47,8 +49,9 @@ public class MainPanel extends Fragment {
public static final int BORDERS = 1;
public static final int GEOMETRY = 2;
public static final int FILTERS = 3;
- public static final int VERSIONS = 4;
- public static final int MAKEUP = 5;
+ public static final int DUALCAM = 4;
+ public static final int VERSIONS = 5;
+ public static final int MAKEUP = 6;
private int mCurrentSelected = -1;
private int mPreviousToggleVersions = -1;
@@ -81,6 +84,10 @@ public class MainPanel extends Fragment {
}
break;
}
+ case DUALCAM: {
+ dualCamButton.setSelected(value);
+ break;
+ }
}
}
@@ -106,6 +113,7 @@ public class MainPanel extends Fragment {
bordersButton = (ImageButton) mMainView.findViewById(R.id.borderButton);
geometryButton = (ImageButton) mMainView.findViewById(R.id.geometryButton);
filtersButton = (ImageButton) mMainView.findViewById(R.id.colorsButton);
+ dualCamButton = (ImageButton) mMainView.findViewById(R.id.dualCamButton);
if(SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
makeupButton = (ImageButton) mMainView.findViewById(R.id.makeupButton);
makeupButton.setVisibility(View.VISIBLE);
@@ -144,6 +152,13 @@ public class MainPanel extends Fragment {
showPanel(FILTERS);
}
});
+ dualCamButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showPanel(DUALCAM);
+ }
+ });
+ enableDualCameraButton(DualCameraNativeEngine.getInstance().isLibLoaded());
FilterShowActivity activity = (FilterShowActivity) getActivity();
showImageStatePanel(activity.isShowingImageStatePanel());
@@ -252,6 +267,19 @@ public class MainPanel extends Fragment {
selection(mCurrentSelected, true);
}
+ public void loadCategoryDualCamPanel() {
+ if (mCurrentSelected == DUALCAM) {
+ return;
+ }
+ boolean fromRight = isRightAnimation(DUALCAM);
+ selection(mCurrentSelected, false);
+ CategoryPanel categoryPanel = new CategoryPanel();
+ categoryPanel.setAdapter(DUALCAM);
+ setCategoryFragment(categoryPanel, fromRight);
+ mCurrentSelected = DUALCAM;
+ selection(mCurrentSelected, true);
+ }
+
public void showPanel(int currentPanel) {
switch (currentPanel) {
case LOOKS: {
@@ -270,6 +298,10 @@ public class MainPanel extends Fragment {
loadCategoryFiltersPanel();
break;
}
+ case DUALCAM: {
+ loadCategoryDualCamPanel();
+ break;
+ }
case VERSIONS: {
loadCategoryVersionsPanel();
break;
@@ -334,4 +366,10 @@ public class MainPanel extends Fragment {
showPanel(currentPanel);
transaction.commit();
}
+
+ public void enableDualCameraButton(boolean enable) {
+ if(dualCamButton != null) {
+ dualCamButton.setVisibility(enable?View.VISIBLE:View.GONE);
+ }
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
new file mode 100644
index 000000000..1ce56b3d9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.net.Uri;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageFusion;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+
+public class EditorDualCamFusion extends ImageOnlyEditor {
+ public static final String TAG = EditorDualCamFusion.class.getSimpleName();
+ public static final int ID = R.id.editorDualCamFusion;
+
+ protected ImageFusion mImageFusion;
+ private Button mPickUnderlayBtn;
+ private OnClickListener mPickBtnClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+ }
+ };
+
+ public EditorDualCamFusion() {
+ super(ID);
+ }
+
+ public boolean useUtilityPanel() {
+ return true;
+ }
+
+ @Override
+ public void createEditor(Context context, FrameLayout frameLayout) {
+ super.createEditor(context, frameLayout);
+ if (mImageFusion == null) {
+ mImageFusion = new ImageFusion(context);
+ }
+ mView = mImageShow = mImageFusion;
+ mImageFusion.setEditor(this);
+ }
+
+ @Override
+ public void setUtilityPanelUI(View actionButton, View editControl) {
+ editControl.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void openUtilityPanel(final LinearLayout accessoryViewList) {
+ super.openUtilityPanel(accessoryViewList);
+ mPickUnderlayBtn = (Button) accessoryViewList.findViewById(R.id.applyEffect);
+ updateText();
+ }
+
+ public void setUnderlayImageUri(Uri uri) {
+ FilterRepresentation filter = getLocalRepresentation();
+ if(filter instanceof FilterDualCamFusionRepresentation) {
+ mImageFusion.setUnderlay(uri);
+ commitLocalRepresentation();
+ }
+ }
+
+ private void updateEffectButton(boolean enabled) {
+ mPickUnderlayBtn.setEnabled(enabled);
+ if(enabled) {
+ mPickUnderlayBtn.setOnClickListener(mPickBtnClickListener);
+ mPickUnderlayBtn.setText(R.string.fusion_pick_underlay);
+ } else {
+ mPickUnderlayBtn.setOnClickListener(null);
+ mPickUnderlayBtn.setText(R.string.fusion_pick_point);
+ }
+ }
+
+
+ protected void updateText() {
+ if(mPickUnderlayBtn != null) {
+ updateEffectButton(hasSegment());
+ }
+ }
+
+ private boolean hasSegment() {
+ FilterRepresentation filter = getLocalRepresentation();
+ if(filter instanceof FilterDualCamFusionRepresentation) {
+ return !((FilterDualCamFusionRepresentation) filter).getPoint().equals(-1,-1);
+ }
+ return false;
+ }
+
+ @Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+ FilterRepresentation rep = getLocalRepresentation();
+ if (rep != null && rep instanceof FilterDualCamFusionRepresentation) {
+ FilterDualCamFusionRepresentation dualRep = (FilterDualCamFusionRepresentation) rep;
+ mImageFusion.setRepresentation(dualRep);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java
new file mode 100644
index 000000000..94b511177
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.filters.FilterDualCamSketchRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageDualCamera;
+
+public class EditorDualCamSketch extends ImageOnlyEditor {
+ public static final int ID = R.id.editorDualCamSketch;
+ private static final String LOGTAG = "EditorDualCamSketch";
+ private ImageDualCamera mImageDualCam;
+
+ public EditorDualCamSketch() {
+ super(ID);
+ }
+
+ @Override
+ public void createEditor(Context context, FrameLayout frameLayout) {
+ super.createEditor(context, frameLayout);
+ if (mImageDualCam == null) {
+ mImageDualCam = new ImageDualCamera(context);
+ }
+ mView = mImageShow = mImageDualCam;
+ mImageDualCam.setEditor(this);
+ }
+
+ @Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+ FilterRepresentation rep = getLocalRepresentation();
+ if (rep != null && rep instanceof FilterDualCamSketchRepresentation) {
+ FilterDualCamSketchRepresentation dualRep = (FilterDualCamSketchRepresentation) rep;
+ mImageDualCam.setRepresentation(dualRep);
+ }
+ }
+
+ @Override
+ public boolean showsSeekBar() {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java
new file mode 100644
index 000000000..f2c7091ba
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageDualCamera;
+
+public class EditorDualCamera extends BasicEditor {
+ public static final int ID = R.id.editorDualCam;
+ private static final String LOGTAG = "EditorDualCamera";
+ private ImageDualCamera mImageDualCam;
+
+ public EditorDualCamera() {
+ super(ID, R.layout.filtershow_dualcamera_editor, R.id.editorDualCam);
+ }
+
+ @Override
+ public void createEditor(Context context, FrameLayout frameLayout) {
+ super.createEditor(context, frameLayout);
+ mImageDualCam = (ImageDualCamera) mImageShow;
+ mImageDualCam.setEditor(this);
+ }
+
+ @Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+ FilterRepresentation rep = getLocalRepresentation();
+ if (rep != null && rep instanceof FilterDualCamBasicRepresentation) {
+ FilterDualCamBasicRepresentation dualRep = (FilterDualCamBasicRepresentation) rep;
+ mImageDualCam.setRepresentation(dualRep);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java b/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
index 0581835f4..54409923e 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
@@ -61,6 +61,10 @@ public class EditorPanel extends Fragment {
int position = adapter.undo();
masterImage.onHistoryItemClick(position);
((FilterShowActivity)getActivity()).invalidateViews();
+
+ if(!masterImage.hasFusionApplied()) {
+ masterImage.setFusionUnderlay(null);
+ }
}
@Override
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
index e93175a92..f1e7e6c26 100644
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -21,6 +21,7 @@ import android.graphics.Color;
import android.util.Log;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import java.util.ArrayList;
@@ -37,6 +38,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
protected ArrayList<FilterRepresentation> mTools = new ArrayList<FilterRepresentation>();
protected ArrayList<FilterRepresentation> mEffects = new ArrayList<FilterRepresentation>();
protected ArrayList<FilterRepresentation> mMakeup = new ArrayList<FilterRepresentation>();
+ protected ArrayList<FilterRepresentation> mDualCam = new ArrayList<FilterRepresentation>();
private static int mImageBorderSize = 4; // in percent
protected void init() {
@@ -51,7 +53,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
mFilters.put(filterClass, (ImageFilter) filterInstance);
FilterRepresentation rep =
- ((ImageFilter) filterInstance).getDefaultRepresentation();
+ ((ImageFilter) filterInstance).getDefaultRepresentation();
if (rep != null) {
addRepresentation(rep);
}
@@ -141,6 +143,10 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
filters.add(ImageFilterFx.class);
filters.add(ImageFilterBorder.class);
filters.add(ImageFilterColorBorder.class);
+ filters.add(ImageFilterDualCamera.class);
+ filters.add(ImageFilterDualCamFusion.class);
+ filters.add(ImageFilterDualCamSketch.class);
+
if(SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
filters.add(ImageFilterMakeupWhiten.class);
filters.add(ImageFilterMakeupSoften.class);
@@ -157,6 +163,10 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
return mBorders;
}
+ public ArrayList<FilterRepresentation> getDualCamera() {
+ return mDualCam;
+ }
+
public ArrayList<FilterRepresentation> getTools() {
return mTools;
}
@@ -313,6 +323,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
mEffects.add(getRepresentation(ImageFilterNegative.class));
mEffects.add(getRepresentation(ImageFilterEdge.class));
mEffects.add(getRepresentation(ImageFilterKMeans.class));
+ mEffects.add(getRepresentation(ImageFilterRedEye.class));
}
public void addMakeups(Context context) {
@@ -362,8 +373,62 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
mTools.add(getRepresentation(ImageFilterDraw.class));
}
+ public void addDualCam(Context context) {
+ int[] textId = {
+ R.string.focus,
+ R.string.halo,
+ R.string.blur
+ };
+
+ int[] overlayId = {
+ R.drawable.filtershow_dualcam_focus,
+ R.drawable.filtershow_dualcam_halo,
+ R.drawable.filtershow_dualcam_blur
+ };
+
+ String[] serializationNames = {
+ "DUAL_CAM_FOCUS",
+ "DUAL_CAM_HALO",
+ "DUAL_CAM_BLUR"
+ };
+
+ // intensity range as defined by ddm lib
+ int[][] minMaxValues = {
+ {0,5,10},
+ {0,3,7},
+ {0,4,9}
+ };
+
+ FilterDualCamSketchRepresentation none =
+ new FilterDualCamSketchRepresentation(context.getString(R.string.none), 0, 0);
+ none.setEditorId(ImageOnlyEditor.ID);
+ mDualCam.add(none);
+
+ for (int i = 0; i < textId.length; i++) {
+ FilterRepresentation dualCam =
+ new FilterDualCamBasicRepresentation(context.getString(textId[i]),
+ minMaxValues[i][0], minMaxValues[i][1], minMaxValues[i][2]);
+ dualCam.setTextId(textId[i]);
+ dualCam.setOverlayId(overlayId[i]);
+ dualCam.setOverlayOnly(true);
+ dualCam.setSerializationName(serializationNames[i]);
+ mDualCam.add(dualCam);
+ addRepresentation(dualCam);
+ }
+
+ FilterDualCamSketchRepresentation sketch = new FilterDualCamSketchRepresentation(
+ context.getString(R.string.sketch), R.string.sketch, R.raw.sketch);
+ sketch.setOverlayId(R.drawable.filtershow_dualcam_sketch);
+ sketch.setOverlayOnly(true);
+ sketch.setSerializationName("DUAL_CAM_SKETCH");
+ mDualCam.add(sketch);
+ addRepresentation(sketch);
+
+ mDualCam.add(getRepresentation(ImageFilterDualCamFusion.class));
+ }
+
public void removeRepresentation(ArrayList<FilterRepresentation> list,
- FilterRepresentation representation) {
+ FilterRepresentation representation) {
for (int i = 0; i < list.size(); i++) {
FilterRepresentation r = list.get(i);
if (r.getFilterClass() == representation.getFilterClass()) {
@@ -378,5 +443,7 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
filterBorder.setResources(resources);
ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class);
filterFx.setResources(resources);
+ ImageFilterDualCamSketch filterSketch = (ImageFilterDualCamSketch) getFilter(ImageFilterDualCamSketch.class);
+ filterSketch.setResources(resources);
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java
new file mode 100644
index 000000000..3da5f7054
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import java.io.IOException;
+
+import android.graphics.Point;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.filtershow.editors.EditorDualCamera;
+
+
+public class FilterDualCamBasicRepresentation extends FilterBasicRepresentation {
+ private static final String LOGTAG = "FilterDualCameraRepresentation";
+
+ private static final String SERIAL_VALUE = "value";
+ private static final String SERIAL_POINT = "point";
+
+ private Point mPoint = new Point(-1, -1);
+
+ public FilterDualCamBasicRepresentation(String name, int minVal, int defVal, int maxVal) {
+ super(name, minVal, defVal, maxVal);
+ setFilterType(FilterRepresentation.TYPE_DUALCAM);
+ setFilterClass(ImageFilterDualCamera.class);
+ setEditorId(EditorDualCamera.ID);
+ setShowParameterValue(true);
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterDualCamBasicRepresentation representation =
+ new FilterDualCamBasicRepresentation(getName(), 0,0,0);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ super.useParametersFrom(a);
+ if (a instanceof FilterDualCamBasicRepresentation) {
+ FilterDualCamBasicRepresentation representation = (FilterDualCamBasicRepresentation) a;
+ setPoint(representation.getPoint());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterDualCamBasicRepresentation) {
+ FilterDualCamBasicRepresentation dualCam = (FilterDualCamBasicRepresentation) representation;
+ if (dualCam.mPoint.equals(mPoint)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setPoint(int x, int y) {
+ mPoint = new Point(x,y);
+ }
+
+ public void setPoint(Point point) {
+ mPoint = point;
+ }
+
+ public Point getPoint() {
+ return mPoint;
+ }
+
+ @Override
+ public String toString() {
+ return "dualcam - value: " + getValue() + ", point: " + getPoint().toString();
+ }
+
+ // Serialization...
+
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ {
+ writer.name(NAME_TAG);
+ writer.value(getName());
+ writer.name(SERIAL_VALUE);
+ writer.value(getValue());
+ writer.name(SERIAL_POINT);
+ writer.beginArray();
+ writer.value(mPoint.x);
+ writer.value(mPoint.y);
+ writer.endArray();
+ }
+ writer.endObject();
+ }
+
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (name.equalsIgnoreCase(NAME_TAG)) {
+ setName(reader.nextString());
+ } else if (name.equalsIgnoreCase(SERIAL_VALUE)) {
+ setValue(reader.nextInt());
+ } else if (name.equalsIgnoreCase(SERIAL_POINT)) {
+ reader.beginArray();
+ reader.hasNext();
+ mPoint.x = reader.nextInt();
+ reader.hasNext();
+ mPoint.y = reader.nextInt();
+ reader.endArray();
+ } else {
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java
new file mode 100644
index 000000000..0e3598b48
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import java.io.IOException;
+
+import android.graphics.Point;
+import android.net.Uri;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorDualCamFusion;
+
+
+public class FilterDualCamFusionRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterFusionRepresentation";
+ public static final String SERIALIZATION_NAME = "FUSION";
+
+ private static final String SERIAL_UNDERLAY_IMAGE = "image";
+ private static final String SERIAL_POINT = "point";
+
+ private Point mPoint = new Point(-1, -1);
+ private String mUri = "";
+
+ public FilterDualCamFusionRepresentation() {
+ super("Fusion");
+ setSerializationName(SERIALIZATION_NAME);
+ setFilterType(FilterRepresentation.TYPE_DUALCAM);
+ setFilterClass(ImageFilterDualCamFusion.class);
+ setEditorId(EditorDualCamFusion.ID);
+ setShowParameterValue(false);
+ setTextId(R.string.fusion);
+ setOverlayId(R.drawable.filtershow_dualcam_fusion);
+ setOverlayOnly(true);
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterDualCamFusionRepresentation representation =
+ new FilterDualCamFusionRepresentation();
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ @Override
+ protected void copyAllParameters(FilterRepresentation representation) {
+ super.copyAllParameters(representation);
+ representation.useParametersFrom(this);
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ super.useParametersFrom(a);
+ if (a instanceof FilterDualCamFusionRepresentation) {
+ FilterDualCamFusionRepresentation representation = (FilterDualCamFusionRepresentation) a;
+ setPoint(representation.getPoint());
+ setUnderlay(representation.getUnderlay());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterDualCamFusionRepresentation) {
+ FilterDualCamFusionRepresentation fusion = (FilterDualCamFusionRepresentation) representation;
+ if (fusion.mPoint.equals(mPoint) &&
+ fusion.mUri.equals(mUri)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setPoint(int x, int y) {
+ mPoint = new Point(x,y);
+ }
+
+ public void setPoint(Point point) {
+ mPoint = point;
+ }
+
+ public Point getPoint() {
+ return mPoint;
+ }
+
+ public void setUnderlay(Uri uri) {
+ if(uri != null) {
+ mUri = uri.toString();
+ } else {
+ mUri = "";
+ }
+ }
+
+ public void setUnderlay(String uri) {
+ if(uri != null)
+ mUri = uri;
+ else
+ mUri = "";
+ }
+
+ public boolean hasUnderlay() {
+ return (mUri != null) && (mUri.isEmpty() == false);
+ }
+
+ public String getUnderlay() {
+ return mUri;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("fusion - underlay: ").append(getUnderlay());
+ sb.append(", point: ").append(getPoint().toString());
+
+ return sb.toString();
+ }
+
+ // Serialization...
+ public void serializeRepresentation(JsonWriter writer) throws IOException {
+ writer.beginObject();
+ {
+ writer.name(NAME_TAG);
+ writer.value(getName());
+ writer.name(SERIAL_UNDERLAY_IMAGE);
+ writer.value(mUri);
+ writer.name(SERIAL_POINT);
+ writer.beginArray();
+ writer.value(mPoint.x);
+ writer.value(mPoint.y);
+ writer.endArray();
+ }
+ writer.endObject();
+ }
+
+ public void deSerializeRepresentation(JsonReader reader) throws IOException {
+ reader.beginObject();
+ while (reader.hasNext()) {
+ String name = reader.nextName();
+ if (name.equalsIgnoreCase(NAME_TAG)) {
+ setName(reader.nextString());
+ } else if (name.equalsIgnoreCase(SERIAL_UNDERLAY_IMAGE)) {
+ setUnderlay(reader.nextString());
+ } else if (name.equalsIgnoreCase(SERIAL_POINT)) {
+ reader.beginArray();
+ reader.hasNext();
+ mPoint.x = reader.nextInt();
+ reader.hasNext();
+ mPoint.y = reader.nextInt();
+ reader.endArray();
+ } else {
+ reader.skipValue();
+ }
+ }
+ reader.endObject();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDualCamSketchRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDualCamSketchRepresentation.java
new file mode 100644
index 000000000..92b3f156b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDualCamSketchRepresentation.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import com.android.gallery3d.filtershow.editors.EditorDualCamSketch;
+
+
+public class FilterDualCamSketchRepresentation extends FilterDualCamBasicRepresentation {
+ private static final String LOGTAG = "FilterDualCamSketchRepresentation";
+
+ private int mSketchResource = 0;
+
+ public FilterDualCamSketchRepresentation(String name, int nameResId, int sketchResId) {
+ super(name, 0, 0, 0);
+ setFilterType(FilterRepresentation.TYPE_DUALCAM);
+ setFilterClass(ImageFilterDualCamSketch.class);
+ setEditorId(EditorDualCamSketch.ID);
+ setTextId(nameResId);
+ setShowParameterValue(false);
+ mSketchResource = sketchResId;
+ }
+
+ @Override
+ public FilterRepresentation copy() {
+ FilterDualCamSketchRepresentation representation =
+ new FilterDualCamSketchRepresentation(getName(), 0, 0);
+ copyAllParameters(representation);
+ return representation;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ super.useParametersFrom(a);
+ if (a instanceof FilterDualCamSketchRepresentation) {
+ FilterDualCamSketchRepresentation representation = (FilterDualCamSketchRepresentation) a;
+ setSketchResId(representation.getSketchResId());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterDualCamSketchRepresentation) {
+ FilterDualCamSketchRepresentation dualCam = (FilterDualCamSketchRepresentation) representation;
+ if (dualCam.getSketchResId() == mSketchResource) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setSketchResId(int bmResource) {
+ mSketchResource = bmResource;
+ }
+
+ public int getSketchResId() {
+ return mSketchResource;
+ }
+
+ @Override
+ public String toString() {
+ return "dualcam - point: " + getPoint().toString() + ", sketchResId: " + mSketchResource;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
index 36675b71b..198e741c3 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
@@ -48,6 +48,7 @@ public class FilterRepresentation {
public static final byte TYPE_TINYPLANET = 6;
public static final byte TYPE_GEOMETRY = 7;
public static final byte TYPE_MAKEUP = 8;
+ public static final byte TYPE_DUALCAM = 9;
protected static final String NAME_TAG = "Name";
public FilterRepresentation(String name) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
new file mode 100644
index 000000000..bc181e33d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class ImageFilterDualCamFusion extends ImageFilter {
+ private static final String TAG = ImageFilterDualCamFusion.class.getSimpleName();
+
+ private FilterDualCamFusionRepresentation mParameters;
+ private Paint mPaint = new Paint();
+ private Bitmap mFilteredBitmap = null;
+ private Point mPoint = null;
+
+ public ImageFilterDualCamFusion() {
+ mName = "Fusion";
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterDualCamFusionRepresentation parameters = (FilterDualCamFusionRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterDualCamFusionRepresentation getParameters() {
+ return mParameters;
+ }
+
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterDualCamFusionRepresentation();
+ }
+
+ @Override
+ public void freeResources() {
+ if (mFilteredBitmap != null)
+ mFilteredBitmap.recycle();
+ mFilteredBitmap = null;
+ mPoint = null;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+
+ Point point = getParameters().getPoint();
+
+ if(!point.equals(-1,-1)) {
+ long startTime = System.currentTimeMillis();
+ Log.e(TAG, "dual cam fusion - start processing: " + startTime);
+
+ if(!point.equals(mPoint)) {
+ mPoint = point;
+
+ if(mFilteredBitmap == null) {
+ Rect originalBounds = MasterImage.getImage().getOriginalBounds();
+ int origW = originalBounds.width();
+ int origH = originalBounds.height();
+
+ mFilteredBitmap = Bitmap.createBitmap(origW, origH, Bitmap.Config.ARGB_8888);
+ mFilteredBitmap.setHasAlpha(true);
+ }
+
+
+ boolean result = DualCameraNativeEngine.getInstance().getForegroundImg(mPoint.x, mPoint.y,
+ mFilteredBitmap);
+
+ if(result == false) {
+ Log.e(TAG, "Imagelib API failed");
+ return bitmap;
+ }
+ }
+
+ mPaint.reset();
+ if(quality == FilterEnvironment.QUALITY_FINAL) {
+ mPaint.setAntiAlias(true);
+ mPaint.setFilterBitmap(true);
+ mPaint.setDither(true);
+ }
+
+ bitmap.setHasAlpha(true);
+
+ Canvas canvas = new Canvas(bitmap);
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ if(getEnvironment().getImagePreset().getDoApplyGeometry()) {
+ Matrix originalToScreen = getOriginalToScreenMatrix(w, h);
+ canvas.drawBitmap(mFilteredBitmap, originalToScreen, null);
+ } else {
+ canvas.drawBitmap(mFilteredBitmap, null, new Rect(0,0,w,h), null);
+ }
+
+ Log.e(TAG, "dual cam fusion - finish processing: " + (System.currentTimeMillis()-startTime));
+ }
+
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
new file mode 100644
index 000000000..b0acb1a70
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class ImageFilterDualCamSketch extends ImageFilter {
+ private static final String TAG = ImageFilterDualCamSketch.class.getSimpleName();
+
+ private FilterDualCamSketchRepresentation mParameters;
+ private Paint mPaint = new Paint();
+ private Bitmap mFilteredBitmap = null;
+ private Bitmap mSketchBm = null;
+ private int mSketchResId = 0;
+ private Point mPoint = null;
+ private Resources mResources = null;
+
+ public FilterRepresentation getDefaultRepresentation() {
+ return null;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterDualCamSketchRepresentation parameters = (FilterDualCamSketchRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterDualCamSketchRepresentation getParameters() {
+ return mParameters;
+ }
+
+ public void setResources(Resources resources) {
+ mResources = resources;
+ }
+
+ @Override
+ public void freeResources() {
+ if(mFilteredBitmap != null)
+ mFilteredBitmap.recycle();
+ if (mSketchBm != null)
+ mSketchBm.recycle();
+
+ mFilteredBitmap = null;
+ mSketchBm = null;
+ mSketchResId = 0;
+ mPoint = null;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+
+ Point point = getParameters().getPoint();
+ if(!point.equals(-1,-1)) {
+
+ int sketchResId = getParameters().getSketchResId();
+ if (sketchResId == 0) {
+ return bitmap;
+ }
+
+ if (mSketchBm == null || mSketchResId != sketchResId) {
+ loadSketchImage(sketchResId);
+ }
+
+ if (mSketchBm == null) {
+ return bitmap;
+ }
+
+ if(!point.equals(mPoint)) {
+ mPoint = point;
+
+ boolean result = false;
+
+ if(mFilteredBitmap == null) {
+ Rect originalBounds = MasterImage.getImage().getOriginalBounds();
+ int origW = originalBounds.width();
+ int origH = originalBounds.height();
+
+ mFilteredBitmap = Bitmap.createBitmap(origW, origH, Bitmap.Config.ARGB_8888);
+ }
+
+ result = DualCameraNativeEngine.getInstance().applySketch(mSketchBm, mPoint.x, mPoint.y, mFilteredBitmap);
+
+ if(result == false) {
+ Log.e(TAG, "Imagelib API failed");
+ return bitmap;
+ }
+ }
+
+ if(quality == FilterEnvironment.QUALITY_FINAL) {
+ mPaint.reset();
+ mPaint.setAntiAlias(true);
+ mPaint.setFilterBitmap(true);
+ mPaint.setDither(true);
+ }
+
+ Canvas canvas = new Canvas(bitmap);
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ if(getEnvironment().getImagePreset().getDoApplyGeometry()) {
+ Matrix originalToScreen = getOriginalToScreenMatrix(w, h);
+ canvas.drawBitmap(mFilteredBitmap, originalToScreen, mPaint);
+ } else {
+ canvas.drawBitmap(mFilteredBitmap, null, new Rect(0,0,w,h), mPaint);
+ }
+ }
+
+ return bitmap;
+ }
+
+ private void loadSketchImage(int sketchResId) {
+ if(mResources == null) {
+ Log.w(TAG, "resources not set");
+ return;
+ }
+
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inScaled = false;
+ mSketchResId = sketchResId;
+ if (mSketchResId != 0) {
+ mSketchBm = BitmapFactory.decodeResource(mResources, mSketchResId, o);
+ if(mSketchBm == null) {
+ Log.w(TAG, "could not decode sketch image");
+ }
+ } else {
+ Log.w(TAG, "bad sketch resource for filter: " + mName);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
new file mode 100644
index 000000000..31e7d0318
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class ImageFilterDualCamera extends ImageFilter {
+ private static final String TAG = ImageFilterDualCamera.class.getSimpleName();
+
+ private FilterDualCamBasicRepresentation mParameters;
+ private Paint mPaint = new Paint();
+ private Bitmap mFilteredBitmap = null;
+ private Point mPoint = null;
+ private int mIntensity = -1;
+
+ public FilterRepresentation getDefaultRepresentation() {
+ return null;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterDualCamBasicRepresentation parameters = (FilterDualCamBasicRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterDualCamBasicRepresentation getParameters() {
+ return mParameters;
+ }
+
+ @Override
+ public void freeResources() {
+ if(mFilteredBitmap != null)
+ mFilteredBitmap.recycle();
+
+ mFilteredBitmap = null;
+ mPoint = null;
+ mIntensity = -1;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
+
+ Point point = getParameters().getPoint();
+ int intensity = getParameters().getValue();
+
+ if(!point.equals(-1,-1)) {
+
+ // if parameters change, generate new filtered bitmap
+ if(!point.equals(mPoint) || mIntensity != intensity) {
+ mPoint = point;
+ mIntensity = intensity;
+
+ if(mFilteredBitmap == null) {
+ Rect originalBounds = MasterImage.getImage().getOriginalBounds();
+ int origW = originalBounds.width();
+ int origH = originalBounds.height();
+
+ mFilteredBitmap = Bitmap.createBitmap(origW, origH, Bitmap.Config.ARGB_8888);
+ }
+
+ boolean result = false;
+
+ switch(mParameters.getTextId()) {
+ case R.string.focus:
+ result = DualCameraNativeEngine.getInstance().applyFocus(mPoint.x, mPoint.y, mIntensity,
+ mFilteredBitmap);
+ break;
+ case R.string.halo:
+ result = DualCameraNativeEngine.getInstance().applyHalo(mPoint.x, mPoint.y, mIntensity,
+ mFilteredBitmap);
+ break;
+ case R.string.blur:
+ result = DualCameraNativeEngine.getInstance().applyBokeh(mPoint.x, mPoint.y, mIntensity,
+ mFilteredBitmap);
+ break;
+ }
+
+ if(result == false) {
+ Log.e(TAG, "Imagelib API failed");
+ return bitmap;
+ }
+ }
+
+ if(quality == FilterEnvironment.QUALITY_FINAL) {
+ mPaint.reset();
+ mPaint.setAntiAlias(true);
+ mPaint.setFilterBitmap(true);
+ mPaint.setDither(true);
+ }
+
+ Canvas canvas = new Canvas(bitmap);
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ if(getEnvironment().getImagePreset().getDoApplyGeometry()) {
+ Matrix originalToScreen = getOriginalToScreenMatrix(w, h);
+ canvas.drawBitmap(mFilteredBitmap, originalToScreen, mPaint);
+ } else {
+ canvas.drawBitmap(mFilteredBitmap, null, new Rect(0,0,w,h), mPaint);
+ }
+ }
+
+ return bitmap;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
new file mode 100644
index 000000000..962519373
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.gallery3d.filtershow.editors.Editor;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+
+public class ImageDualCamera extends ImageShow {
+ private static final String LOGTAG = "ImageDualCamera";
+ protected Editor mEditor;
+ protected FilterDualCamBasicRepresentation mRepresentation;
+ private Matrix mToOrig;
+ private float[] mTmpPoint = new float[2];
+
+ public ImageDualCamera(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ImageDualCamera(Context context) {
+ super(context);
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent event) {
+ Log.e(LOGTAG, "single tap: " + event.getX() + "x" + event.getY());
+ calcScreenMapping();
+ mTmpPoint[0] = event.getX();
+ mTmpPoint[1] = event.getY();
+ mToOrig.mapPoints(mTmpPoint);
+
+ mRepresentation.setPoint((int)mTmpPoint[0], (int)mTmpPoint[1]);
+ mEditor.commitLocalRepresentation();
+ return true;
+ }
+
+ public void setEditor(Editor editor) {
+ mEditor = editor;
+ }
+
+ public void setRepresentation(FilterDualCamBasicRepresentation representation) {
+ mRepresentation = representation;
+ }
+
+ private void calcScreenMapping() {
+ mToOrig = getScreenToImageMatrix(true);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java b/src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java
new file mode 100644
index 000000000..6d4ef9fc7
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.editors.EditorDualCamFusion;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+
+public class ImageFusion extends ImageShow {
+ private static final String LOGTAG = "ImageFusion";
+ protected EditorDualCamFusion mEditor;
+ protected FilterDualCamFusionRepresentation mRepresentation;
+ private Matrix mToOrig;
+ private float[] mTmpPoint = new float[2];
+ private Bitmap mUnderlay;
+
+ public ImageFusion(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mAllowScaleAndTranslate = true;
+ }
+
+ public ImageFusion(Context context) {
+ super(context);
+ mAllowScaleAndTranslate = true;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent event) {
+ Log.d(LOGTAG, "single tap: " + event.getX() + "x" + event.getY());
+ calcScreenMapping();
+ mTmpPoint[0] = event.getX();
+ mTmpPoint[1] = event.getY();
+ mToOrig.mapPoints(mTmpPoint);
+
+ mRepresentation.setPoint((int)mTmpPoint[0], (int)mTmpPoint[1]);
+ mEditor.commitLocalRepresentation();
+ return true;
+ }
+
+ public void setUnderlay(Uri uri) {
+ mRepresentation.setUnderlay(uri);
+
+ mUnderlay = ImageLoader.loadConstrainedBitmap(uri, getContext(), MasterImage.MAX_BITMAP_DIM, new Rect(), false);
+ MasterImage.getImage().setFusionUnderlay(mUnderlay);
+ invalidate();
+ }
+
+ public void setEditor(EditorDualCamFusion editor) {
+ mEditor = editor;
+ }
+
+ public void setRepresentation(FilterDualCamFusionRepresentation representation) {
+ mRepresentation = representation;
+ }
+
+ private void calcScreenMapping() {
+ mToOrig = getScreenToImageMatrix(true);
+ }
+
+ @Override
+ public boolean enableComparison() {
+ return false;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index d7c2eb4f8..9ca143fde 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -16,6 +16,9 @@
package com.android.gallery3d.filtershow.imageshow;
+import java.io.File;
+import java.util.ArrayList;
+
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
@@ -30,11 +33,11 @@ import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.NinePatchDrawable;
import android.support.v4.widget.EdgeEffectCompat;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
@@ -51,12 +54,9 @@ import com.android.gallery3d.filtershow.filters.ImageFilter;
import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.tools.SaveImage;
-import java.io.File;
-import java.util.ArrayList;
-
public class ImageShow extends View implements OnGestureListener,
- ScaleGestureDetector.OnScaleGestureListener,
- OnDoubleTapListener {
+ ScaleGestureDetector.OnScaleGestureListener,
+ OnDoubleTapListener {
private static final String LOGTAG = "ImageShow";
private static final boolean ENABLE_ZOOMED_COMPARISON = false;
@@ -70,14 +70,15 @@ public class ImageShow extends View implements OnGestureListener,
private GestureDetector mGestureDetector = null;
private ScaleGestureDetector mScaleGestureDetector = null;
+ private RectF mFusionBounds = new RectF();
protected Rect mImageBounds = new Rect();
private boolean mOriginalDisabled = false;
private boolean mTouchShowOriginal = false;
private long mTouchShowOriginalDate = 0;
private final long mTouchShowOriginalDelayMin = 200; // 200ms
private int mShowOriginalDirection = 0;
- private static int UNVEIL_HORIZONTAL = 1;
- private static int UNVEIL_VERTICAL = 2;
+ private static final int UNVEIL_HORIZONTAL = 1;
+ private static final int UNVEIL_VERTICAL = 2;
private NinePatchDrawable mShadow = null;
private Rect mShadowBounds = new Rect();
@@ -110,6 +111,8 @@ public class ImageShow extends View implements OnGestureListener,
private ValueAnimator mAnimatorTranslateX = null;
private ValueAnimator mAnimatorTranslateY = null;
+ protected boolean mAllowScaleAndTranslate = false;
+
private enum InteractionMode {
NONE,
SCALE,
@@ -143,6 +146,10 @@ public class ImageShow extends View implements OnGestureListener,
return MasterImage.getImage().hasModifications();
}
+ public boolean hasFusionApplied() {
+ return MasterImage.getImage().hasFusionApplied();
+ }
+
public void resetParameter() {
// TODO: implement reset
}
@@ -273,6 +280,34 @@ public class ImageShow extends View implements OnGestureListener,
mActivity.stopLoadingIndicator();
}
+ Bitmap fusionUnderlay = MasterImage.getImage().getFusionUnderlay();
+ if(fusionUnderlay != null) {
+ float canvWidth = canvas.getWidth();
+ float canvHeight = canvas.getHeight();
+ float width, height;
+ float underlayAspect = (float)fusionUnderlay.getWidth() / (float)fusionUnderlay.getHeight();
+
+ if(canvHeight * underlayAspect > canvWidth) {
+ // width is constraint
+ width = canvWidth;
+ height = canvWidth / underlayAspect;
+ } else {
+ // height is constraint
+ height = canvHeight;
+ width = canvHeight * underlayAspect;
+ }
+
+ // center in canvas
+ mFusionBounds.top = (canvHeight - height)/2;
+ mFusionBounds.bottom = mFusionBounds.top + height;
+ mFusionBounds.left = (canvWidth - width)/2;
+ mFusionBounds.right = mFusionBounds.left + width;
+
+ canvas.drawBitmap(fusionUnderlay, null, mFusionBounds, null);
+ canvas.clipRect(mFusionBounds, Region.Op.REPLACE);
+ MasterImage.getImage().setFusionBounds(canvas, mFusionBounds);
+ }
+
canvas.save();
mShadowDrawn = false;
@@ -350,7 +385,7 @@ public class ImageShow extends View implements OnGestureListener,
}
public void drawImageAndAnimate(Canvas canvas,
- Bitmap image) {
+ Bitmap image) {
if (image == null) {
return;
}
@@ -366,6 +401,8 @@ public class ImageShow extends View implements OnGestureListener,
m.mapRect(d);
d.roundOut(mImageBounds);
+ master.setImageBounds(canvas, mImageBounds);
+
boolean showAnimatedImage = master.onGoingNewLookAnimation();
if (!showAnimatedImage && mDidStartAnimation) {
// animation ended, but do we have the correct image to show?
@@ -477,12 +514,20 @@ public class ImageShow extends View implements OnGestureListener,
if (needsToDrawImage) {
drawShadow(canvas, previousBounds); // as needed
+
+ if(hasFusionApplied() || this instanceof ImageFusion) {
+ previousImage.setHasAlpha(true);
+ }
canvas.drawBitmap(previousImage, mp, mPaint);
}
canvas.restore();
} else {
drawShadow(canvas, mImageBounds); // as needed
+
+ if(hasFusionApplied() || this instanceof ImageFusion) {
+ image.setHasAlpha(true);
+ }
canvas.drawBitmap(image, m, mPaint);
}
@@ -504,7 +549,7 @@ public class ImageShow extends View implements OnGestureListener,
}
private void drawShadow(Canvas canvas, Rect d) {
- if (!mShadowDrawn) {
+ if (!mShadowDrawn && !hasFusionApplied() && !(this instanceof ImageFusion)) {
mShadowBounds.set(d.left - mShadowMargin, d.top - mShadowMargin,
d.right + mShadowMargin, d.bottom + mShadowMargin);
mShadow.setBounds(mShadowBounds);
@@ -614,9 +659,12 @@ public class ImageShow extends View implements OnGestureListener,
int action = event.getAction();
action = action & MotionEvent.ACTION_MASK;
- mGestureDetector.onTouchEvent(event);
+ if(!hasFusionApplied() || mAllowScaleAndTranslate)
+ mGestureDetector.onTouchEvent(event);
boolean scaleInProgress = scaleInProgress();
- mScaleGestureDetector.onTouchEvent(event);
+ if(!hasFusionApplied() || mAllowScaleAndTranslate)
+ mScaleGestureDetector.onTouchEvent(event);
+
if (mInteractionMode == InteractionMode.SCALE) {
return true;
}
@@ -642,7 +690,8 @@ public class ImageShow extends View implements OnGestureListener,
mTouch.y = ey;
float scaleFactor = MasterImage.getImage().getScaleFactor();
- if (scaleFactor > 1 && (!ENABLE_ZOOMED_COMPARISON || event.getPointerCount() == 2)) {
+ if ((scaleFactor > 1 && (!ENABLE_ZOOMED_COMPARISON || event.getPointerCount() == 2) && !hasFusionApplied())
+ || mAllowScaleAndTranslate) {
float translateX = (mTouch.x - mTouchDown.x) / scaleFactor;
float translateY = (mTouch.y - mTouchDown.y) / scaleFactor;
Point originalTranslation = MasterImage.getImage().getOriginalTranslation();
@@ -654,7 +703,7 @@ public class ImageShow extends View implements OnGestureListener,
} else if (enableComparison() && !mOriginalDisabled
&& (System.currentTimeMillis() - mTouchShowOriginalDate
> mTouchShowOriginalDelayMin)
- && event.getPointerCount() == 1) {
+ && event.getPointerCount() == 1) {
mTouchShowOriginal = true;
}
}
@@ -668,7 +717,8 @@ public class ImageShow extends View implements OnGestureListener,
mTouchDown.y = 0;
mTouch.x = 0;
mTouch.y = 0;
- if (MasterImage.getImage().getScaleFactor() <= 1) {
+ if (!(mAllowScaleAndTranslate || hasFusionApplied()) &&
+ MasterImage.getImage().getScaleFactor() <= 1) {
MasterImage.getImage().setScaleFactor(1);
MasterImage.getImage().resetTranslation();
}
@@ -684,7 +734,7 @@ public class ImageShow extends View implements OnGestureListener,
}
private void startAnimTranslation(int fromX, int toX,
- int fromY, int toY, int delay) {
+ int fromY, int toY, int delay) {
if (fromX == toX && fromY == toY) {
return;
}
@@ -729,8 +779,8 @@ public class ImageShow extends View implements OnGestureListener,
if (x != translation.x || y != translation.y) {
startAnimTranslation(x, translation.x,
- y, translation.y,
- mAnimationSnapDelay);
+ y, translation.y,
+ mAnimationSnapDelay);
}
}
@@ -740,6 +790,9 @@ public class ImageShow extends View implements OnGestureListener,
@Override
public boolean onDoubleTap(MotionEvent arg0) {
+ if(hasFusionApplied())
+ return true;
+
mZoomIn = !mZoomIn;
float scale = 1.0f;
final float x = arg0.getX();
@@ -754,7 +807,7 @@ public class ImageShow extends View implements OnGestureListener,
mAnimatorScale = ValueAnimator.ofFloat(
MasterImage.getImage().getScaleFactor(),
scale
- );
+ );
float translateX = (getWidth() / 2 - x);
float translateY = (getHeight() / 2 - y);
Point translation = MasterImage.getImage().getTranslation();
@@ -770,8 +823,8 @@ public class ImageShow extends View implements OnGestureListener,
constrainTranslation(translation, scale);
startAnimTranslation(startTranslateX, translation.x,
- startTranslateY, translation.y,
- mAnimationZoomDelay);
+ startTranslateY, translation.y,
+ mAnimationZoomDelay);
mAnimatorScale.setDuration(mAnimationZoomDelay);
mAnimatorScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
@@ -809,7 +862,7 @@ public class ImageShow extends View implements OnGestureListener,
private void constrainTranslation(Point translation, float scale) {
int currentEdgeEffect = 0;
- if (scale <= 1) {
+ if (mAllowScaleAndTranslate || scale <= 1) {
mCurrentEdgeEffect = 0;
mEdgeEffect.finish();
return;
@@ -929,9 +982,11 @@ public class ImageShow extends View implements OnGestureListener,
if (scaleFactor > MasterImage.getImage().getMaxScaleFactor()) {
scaleFactor = MasterImage.getImage().getMaxScaleFactor();
}
- if (scaleFactor < 1.0f) {
+
+ if (!mAllowScaleAndTranslate && scaleFactor < 1.0f) {
scaleFactor = 1.0f;
}
+
MasterImage.getImage().setScaleFactor(scaleFactor);
scaleFactor = img.getScaleFactor();
float focusx = detector.getFocusX();
@@ -961,7 +1016,8 @@ public class ImageShow extends View implements OnGestureListener,
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
mInteractionMode = InteractionMode.NONE;
- if (MasterImage.getImage().getScaleFactor() < 1) {
+ if (!mAllowScaleAndTranslate &&
+ MasterImage.getImage().getScaleFactor() < 1) {
MasterImage.getImage().setScaleFactor(1);
invalidate();
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index 5e27f4213..2ef0b8362 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -16,9 +16,16 @@
package com.android.gallery3d.filtershow.imageshow;
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Vector;
+
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
@@ -31,6 +38,7 @@ import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
@@ -45,9 +53,8 @@ import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
import com.android.gallery3d.filtershow.pipeline.SharedBuffer;
import com.android.gallery3d.filtershow.pipeline.SharedPreset;
import com.android.gallery3d.filtershow.state.StateAdapter;
-
-import java.util.List;
-import java.util.Vector;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+import com.android.gallery3d.mpo.MpoParser;
public class MasterImage implements RenderingRequestCaller {
@@ -73,6 +80,7 @@ public class MasterImage implements RenderingRequestCaller {
private Bitmap mOriginalBitmapLarge = null;
private Bitmap mOriginalBitmapHighres = null;
private Bitmap mTemporaryThumbnail = null;
+
private int mOrientation;
private Rect mOriginalBounds;
private final Vector<ImageShow> mLoadListeners = new Vector<ImageShow>();
@@ -87,6 +95,10 @@ public class MasterImage implements RenderingRequestCaller {
private int mShadowMargin = 15; // not scaled, fixed in the asset
private Rect mPartialBounds = new Rect();
+ private Bitmap mFusionUnderlay = null;
+ private Rect mImageBounds = null;
+ private Rect mFusionBounds = null;
+
private ValueAnimator mAnimator = null;
private float mMaskScale = 1;
private boolean mOnGoingNewLookAnimation = false;
@@ -328,6 +340,15 @@ public class MasterImage implements RenderingRequestCaller {
}
}
+ public synchronized boolean hasFusionApplied() {
+ FilterRepresentation representation =
+ mPreset.getFilterWithSerializationName(FilterDualCamFusionRepresentation.SERIALIZATION_NAME);
+ if(representation instanceof FilterDualCamFusionRepresentation) {
+ return true;
+ }
+ return false;
+ }
+
public SharedBuffer getPreviewBuffer() {
return mPreviewBuffer;
}
@@ -619,11 +640,11 @@ public class MasterImage implements RenderingRequestCaller {
mImageShowSize.x / 2.0f,
mImageShowSize.y / 2.0f);
m.postTranslate(translation.x * getScaleFactor(),
- translation.y * getScaleFactor());
+ translation.y * getScaleFactor());
return m;
}
- private Matrix getImageToScreenMatrix(boolean reflectRotation) {
+ public Matrix getImageToScreenMatrix(boolean reflectRotation) {
if (getOriginalBounds() == null || mImageShowSize.x == 0 || mImageShowSize.y == 0) {
return new Matrix();
}
@@ -840,4 +861,116 @@ public class MasterImage implements RenderingRequestCaller {
public boolean hasTinyPlanet() {
return mPreset.contains(FilterRepresentation.TYPE_TINYPLANET);
}
+
+ public boolean loadMpo() {
+ boolean loaded = false;
+ MpoParser parser = MpoParser.parse(getActivity(), getUri());
+ byte[] primaryMpoData = parser.readImgData(true);
+ byte[] auxiliaryMpoData = parser.readImgData(false);
+
+ if(primaryMpoData != null && auxiliaryMpoData != null) {
+ Bitmap primaryBm = BitmapFactory.decodeByteArray(primaryMpoData, 0, primaryMpoData.length);
+ primaryMpoData = null;
+
+ if(primaryBm == null) {
+ return false;
+ }
+
+ int primaryWidth = primaryBm.getWidth();
+ int primaryHeight = primaryBm.getHeight();
+ int primaryStride = primaryBm.getRowBytes();
+
+ Log.v(LOGTAG, "primary info: " + primaryWidth + "x" + primaryHeight + ", s:" + primaryStride);
+
+ ByteBuffer primaryMpoBuffer = ByteBuffer.allocateDirect(primaryBm.getByteCount());
+ primaryBm.copyPixelsToBuffer(primaryMpoBuffer);
+ primaryBm.recycle();
+ primaryBm = null;
+
+ // check for pre-generated dm file
+ String mpoFilepath = ImageLoader.getLocalPathFromUri(getActivity(), getUri());
+ String depthFilepath = MpoParser.getDepthmapFilepath(mpoFilepath);
+ File depthFile = new File(depthFilepath);
+ if(depthFile.exists()) {
+ // TODO: read from depth map file and init DDM
+ // ByteBuffer depthMap = MpoParser.readDepthMapFile(depthFilepath);
+ //
+ // DualCameraNativeEngine.getInstance().loadDepthMap(
+ // mPrimaryMpoImg, primaryWidth, primaryHeight, primaryStride,
+ // depthMap, depthMapWidth, depthMapHeight, depthMapStride);
+
+ } else {
+ // read auxiliary image and generate depth map.
+ Bitmap auxiliaryBm = BitmapFactory.decodeByteArray(auxiliaryMpoData, 0, auxiliaryMpoData.length);
+ auxiliaryMpoData = null;
+
+ if(auxiliaryBm == null) {
+ return false;
+ }
+
+ int auxiliaryWidth = auxiliaryBm.getWidth();
+ int auxiliaryHeight = auxiliaryBm.getHeight();
+ int auxiliaryStride = auxiliaryBm.getRowBytes();
+
+ Log.v(LOGTAG, "auxiliary info: " + auxiliaryWidth + "x" + auxiliaryHeight + ", s:" + auxiliaryStride);
+
+ ByteBuffer auxiliaryMpoBuffer = ByteBuffer.allocateDirect(auxiliaryBm.getByteCount());
+ auxiliaryBm.copyPixelsToBuffer(auxiliaryMpoBuffer);
+ auxiliaryBm.recycle();
+ auxiliaryBm = null;
+
+ DualCameraNativeEngine.getInstance().initDepthMap(
+ primaryMpoBuffer, primaryWidth, primaryHeight, primaryStride,
+ auxiliaryMpoBuffer, auxiliaryWidth, auxiliaryHeight, auxiliaryStride,
+ mpoFilepath, DualCameraNativeEngine.getInstance().getCalibFilepath(mActivity));
+
+ Point size = new Point();
+ boolean result = DualCameraNativeEngine.getInstance().getDepthMapSize(size);
+ if(result) {
+ Log.v(LOGTAG, "get depthmapsize returned true. size: " + size.x + "x" + size.y);
+
+ Bitmap depthMap = Bitmap.createBitmap(size.x, size.y, Config.ALPHA_8);
+ if(DualCameraNativeEngine.getInstance().getDepthMap(depthMap)) {
+ loaded = true;
+
+ // TODO: write and read depth map.
+ // MpoParser.writeDepthMapFile(depthFilepath, depthMap);
+ } else {
+ Log.w(LOGTAG, "get depthmap returned false");
+ }
+
+ depthMap.recycle();
+ depthMap = null;
+ } else {
+ Log.w(LOGTAG, "get depthmapsize returned false");
+ }
+ }
+ }
+ return loaded;
+ }
+
+ public void setFusionUnderlay(Bitmap underlay) {
+ mFusionUnderlay = underlay;
+ }
+
+ public Bitmap getFusionUnderlay() {
+ return mFusionUnderlay;
+ }
+
+ public void setFusionBounds(Canvas canvas, RectF bounds) {
+ if(mFusionBounds == null) mFusionBounds = new Rect();
+ bounds.roundOut(mFusionBounds);
+ }
+
+ public Rect getFusionBounds() {
+ return mFusionBounds;
+ }
+
+ public void setImageBounds(Canvas canvas, Rect bounds) {
+ mImageBounds = bounds;
+ }
+
+ public Rect getImageBounds() {
+ return mImageBounds;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
index a487a5d8d..0cdbed76d 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
@@ -18,9 +18,9 @@ package com.android.gallery3d.filtershow.pipeline;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.PorterDuff;
import android.renderscript.Allocation;
import android.renderscript.RenderScript;
-import android.util.Log;
import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
@@ -58,6 +58,7 @@ public class Buffer {
public synchronized void useBitmap(Bitmap bitmap) {
Canvas canvas = new Canvas(mBitmap);
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawBitmap(bitmap, 0, 0, null);
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
index c2912ed78..f57383a8c 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java
@@ -28,7 +28,7 @@ import java.util.Vector;
public class CacheProcessing {
private static final String LOGTAG = "CacheProcessing";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
private static final boolean NO_CACHING = false;
private Vector<CacheStep> mSteps = new Vector<CacheStep>();
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
index 1460ad434..51eabe986 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
@@ -16,6 +16,13 @@
package com.android.gallery3d.filtershow.pipeline;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Vector;
+
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.renderscript.Allocation;
@@ -24,10 +31,11 @@ import android.util.JsonWriter;
import android.util.Log;
import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.cache.BitmapCache;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamSketchRepresentation;
import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
@@ -42,13 +50,6 @@ import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.state.State;
import com.android.gallery3d.filtershow.state.StateAdapter;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Vector;
-
public class ImagePreset {
private static final String LOGTAG = "ImagePreset";
@@ -165,6 +166,10 @@ public class ImagePreset {
mDoApplyGeometry = value;
}
+ public boolean getDoApplyGeometry() {
+ return mDoApplyGeometry;
+ }
+
public void setDoApplyFilters(boolean value) {
mDoApplyFilters = value;
}
@@ -327,11 +332,17 @@ public class ImagePreset {
}
public void removeFilter(FilterRepresentation filterRepresentation) {
- if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
+ if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER
+ || filterRepresentation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
for (int i = 0; i < mFilters.size(); i++) {
- if (mFilters.elementAt(i).getFilterType()
- == filterRepresentation.getFilterType()) {
+ FilterRepresentation filter = mFilters.elementAt(i);
+ if (filter.getFilterType() == filterRepresentation.getFilterType()) {
mFilters.remove(i);
+
+ // reset fusion underlay image.
+ if(filter instanceof FilterDualCamFusionRepresentation) {
+ MasterImage.getImage().setFusionUnderlay(null);
+ }
break;
}
}
@@ -350,7 +361,7 @@ public class ImagePreset {
if (representation instanceof FilterUserPresetRepresentation) {
ImagePreset preset = ((FilterUserPresetRepresentation) representation).getImagePreset();
if (preset.nbFilters() == 1
- && preset.contains(FilterRepresentation.TYPE_FX)) {
+ && preset.contains(FilterRepresentation.TYPE_FX)) {
FilterRepresentation rep = preset.getFilterRepresentationForType(
FilterRepresentation.TYPE_FX);
addFilter(rep);
@@ -383,6 +394,11 @@ public class ImagePreset {
if (!isNoneBorderFilter(representation)) {
mFilters.add(representation);
}
+ } else if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+ removeFilter(representation);
+ if (!isNoneDualCamFilter(representation)) {
+ mFilters.add(representation);
+ }
} else if (representation.getFilterType() == FilterRepresentation.TYPE_FX) {
boolean replaced = false;
for (int i = 0; i < mFilters.size(); i++) {
@@ -402,20 +418,36 @@ public class ImagePreset {
} else {
mFilters.add(representation);
}
- // Enforces Filter type ordering for borders
+
+ // Enforces Filter type ordering for borders and dual cam
FilterRepresentation border = null;
+ FilterRepresentation dualcam = null;
for (int i = 0; i < mFilters.size();) {
FilterRepresentation rep = mFilters.elementAt(i);
if (rep.getFilterType() == FilterRepresentation.TYPE_BORDER) {
border = rep;
mFilters.remove(i);
continue;
+ } else if (rep.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+ dualcam = rep;
+ mFilters.remove(i);
+ continue;
}
i++;
}
if (border != null) {
mFilters.add(border);
}
+ if (dualcam != null) {
+ int i = 0;
+ for (; i < mFilters.size(); i++) {
+ FilterRepresentation rep = mFilters.elementAt(i);
+ if (rep.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
+ break;
+ }
+ }
+ mFilters.add(i, dualcam);
+ }
}
private boolean isNoneBorderFilter(FilterRepresentation representation) {
@@ -428,6 +460,11 @@ public class ImagePreset {
((FilterFxRepresentation) representation).getNameResource() == R.string.none;
}
+ private boolean isNoneDualCamFilter(FilterRepresentation representation) {
+ return representation instanceof FilterDualCamSketchRepresentation &&
+ ((FilterDualCamSketchRepresentation) representation).getSketchResId() == 0;
+ }
+
public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
for (int i = 0; i < mFilters.size(); i++) {
FilterRepresentation representation = mFilters.elementAt(i);
@@ -440,6 +477,7 @@ public class ImagePreset {
public Bitmap apply(Bitmap original, FilterEnvironment environment) {
Bitmap bitmap = original;
+ bitmap = applyDualCamera(bitmap, environment);
bitmap = applyFilters(bitmap, -1, -1, environment);
return applyBorder(bitmap, environment);
}
@@ -483,6 +521,25 @@ public class ImagePreset {
return bitmap;
}
+ public Bitmap applyDualCamera(Bitmap bitmap, FilterEnvironment environment) {
+ // Apply dual camera filters
+ // Returns a new bitmap.
+ for (FilterRepresentation representation:mFilters) {
+ if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+ Bitmap tmp = bitmap;
+ bitmap = environment.applyRepresentation(representation, bitmap);
+ if (tmp != bitmap) {
+ environment.cache(tmp);
+ }
+ if (environment.needsStop()) {
+ return bitmap;
+ }
+ }
+ }
+
+ return bitmap;
+ }
+
public Bitmap applyBorder(Bitmap bitmap, FilterEnvironment environment) {
// get the border from the list of filters.
FilterRepresentation border = getFilterRepresentationForType(
@@ -519,6 +576,10 @@ public class ImagePreset {
// TODO: might be worth getting rid of applyBorder.
continue;
}
+ if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+ // skip the dual cam as it's already applied.
+ continue;
+ }
Bitmap tmp = bitmap;
bitmap = environment.applyRepresentation(representation, bitmap);
if (tmp != bitmap) {
@@ -659,7 +720,7 @@ public class ImagePreset {
writer.endObject();
} catch (IOException e) {
- Log.e(LOGTAG,"Error encoding JASON",e);
+ Log.e(LOGTAG,"Error encoding JASON",e);
}
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
index e334e8798..dbf6a8d88 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
@@ -28,6 +28,7 @@ import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
+
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.filters.FiltersManager;
@@ -304,6 +305,7 @@ public class ProcessingService extends Service {
filtersManager.addBorders(this);
filtersManager.addTools(this);
filtersManager.addEffects();
+ filtersManager.addDualCam(this);
filtersManager.addMakeups(this);
FiltersManager highresFiltersManager = FiltersManager.getHighresManager();
@@ -311,6 +313,7 @@ public class ProcessingService extends Service {
highresFiltersManager.addBorders(this);
highresFiltersManager.addTools(this);
highresFiltersManager.addEffects();
+ highresFiltersManager.addDualCam(this);
// highresFiltersManager.addMakeups(this);
}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
index 4cb9e5ad5..300dfe979 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
@@ -84,6 +84,10 @@ public class RenderingRequest {
request.setBounds(bounds);
request.setDestination(destination);
passedPreset.setPartialRendering(true, bounds);
+ } else if (type == GEOMETRY_RENDERING ||
+ type == FILTERS_RENDERING) {
+ passedPreset.setDoApplyGeometry(preset.getDoApplyGeometry());
+ passedPreset.setDoApplyFilters(preset.getDoApplyFilters());
}
request.setImagePreset(passedPreset);
diff --git a/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java b/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
new file mode 100644
index 000000000..60b4d67e9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.filtershow.tools;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.util.Log;
+
+public class DualCameraNativeEngine {
+ private static final String TAG = "DualCameraNativeEngine";
+ static {
+ try {
+ System.loadLibrary("jni_dualcamera");
+ mLibLoaded = true;
+ Log.v(TAG, "successfully loaded dual camera lib");
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "failed to load dual camera lib");
+ mLibLoaded = false;
+ }
+ }
+
+ public static final String DEPTH_MAP_EXT = "dm";
+ private static final String CALIBRATION_FILENAME = "ddm_calib_file.dat";
+ private static boolean mLibLoaded;
+
+ private static DualCameraNativeEngine mInstance;
+
+ private DualCameraNativeEngine() {}
+
+ public static void createInstance() {
+ if(mInstance == null) {
+ mInstance = new DualCameraNativeEngine();
+ }
+ }
+
+ public static DualCameraNativeEngine getInstance() {
+ createInstance();
+ return mInstance;
+ }
+
+ public boolean isLibLoaded() {
+ return mLibLoaded;
+ }
+
+ public String getCalibFilepath(Context context) {
+ File calibFile = new File(context.getFilesDir(), CALIBRATION_FILENAME);
+ return calibFile.getAbsolutePath();
+ }
+
+ native public void initDepthMap(ByteBuffer primaryRGBA, int primaryWidth, int primaryHeight, int primaryStride,
+ ByteBuffer auxiliaryRGBA, int auxiliaryWidth, int auxiliaryHeight, int auxiliaryStride,
+ String mpoFilepath, String calibFilepath);
+
+ native public void loadDepthMap(ByteBuffer primaryRGBA, int primaryWidth, int primaryHeight, int primaryStride,
+ ByteBuffer depthMap, int depthMapWidth, int depthMapHeight, int depthMapStride);
+
+ native public void releaseDepthMap();
+
+ native public boolean getDepthMapSize(Point point);
+
+ native public boolean getDepthMap(Bitmap dataBuffer);
+
+ native public boolean applyFocus(int focusPointX, int focusPointY, int intensity, Bitmap outBm);
+
+ native public boolean applyHalo(int focusPointX, int focusPointY, int intensity, Bitmap outBm);
+
+ native public boolean applyBokeh(int focusPointX, int focusPointY, int intensity, Bitmap outBm);
+
+ native public boolean applySketch(Bitmap sketchBm, int focusPointX, int focusPointY, Bitmap outBm);
+
+ native public boolean getForegroundImg(int focusPointX, int focusPointY, Bitmap outBm);
+}
diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
index d4cc3b02a..f04466f1b 100644
--- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java
+++ b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
@@ -16,12 +16,26 @@
package com.android.gallery3d.filtershow.tools;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.Date;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
@@ -35,6 +49,7 @@ import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
@@ -43,16 +58,6 @@ import com.android.gallery3d.filtershow.pipeline.ImagePreset;
import com.android.gallery3d.filtershow.pipeline.ProcessingService;
import com.android.gallery3d.util.XmpUtilHelper;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-
/**
* Handles saving edited photo
*/
@@ -179,12 +184,12 @@ public class SaveImage {
querySourceFromContentResolver(contentResolver,
srcContentUri, queryProjection,
new ContentResolverQueryCallback() {
- @Override
- public void onCursorResult(Cursor cursor) {
- fullPath[0] = cursor.getString(0);
- }
- }
- );
+ @Override
+ public void onCursorResult(Cursor cursor) {
+ fullPath[0] = cursor.getString(0);
+ }
+ });
+
if (fullPath[0] != null) {
// Construct the auxiliary directory given the source file's path.
// Then select and delete all the files starting with the same name
@@ -415,6 +420,38 @@ public class SaveImage {
"Saving");
bitmap = pipeline.renderFinalImage(bitmap, preset);
+
+ // Check for Fusion
+ FilterDualCamFusionRepresentation fusionRep = (FilterDualCamFusionRepresentation) preset.getFilterWithSerializationName(
+ FilterDualCamFusionRepresentation.SERIALIZATION_NAME);
+
+ if(fusionRep != null && fusionRep.hasUnderlay()) {
+ // fusion. decode underlay image and get dest rect
+ Uri underLayUri = Uri.parse(fusionRep.getUnderlay());
+ Bitmap underlay = ImageLoader.loadBitmapWithBackouts(mContext, underLayUri, sampleSize);
+ RectF destRect = new RectF();
+ Rect imageBounds = MasterImage.getImage().getImageBounds();
+ Rect underlayBounds = MasterImage.getImage().getFusionBounds();
+ float underlayScaleFactor = (float)underlay.getWidth() / (float)underlayBounds.width();
+
+ destRect.left = (imageBounds.left - underlayBounds.left) * underlayScaleFactor;
+ destRect.right = (imageBounds.right - underlayBounds.left) * underlayScaleFactor;
+ destRect.top = (imageBounds.top - underlayBounds.top) * underlayScaleFactor;
+ destRect.bottom = (imageBounds.bottom - underlayBounds.top) * underlayScaleFactor;
+
+ Canvas canvas = new Canvas(underlay);
+ Paint paint = new Paint();
+ paint.reset();
+ paint.setAntiAlias(true);
+ paint.setFilterBitmap(true);
+ paint.setDither(true);
+
+ canvas.drawBitmap(bitmap, null, destRect, paint);
+
+ bitmap.recycle();
+ bitmap = underlay;
+ }
+
updateProgress();
Object xmp = getPanoramaXMPData(newSourceUri, preset);
@@ -542,8 +579,11 @@ public class SaveImage {
if (preset.contains(FilterRepresentation.TYPE_TINYPLANET)){
flatten = true;
}
+
+ float scaleFactor = 1f;
+
Intent processIntent = ProcessingService.getSaveIntent(filterShowActivity, preset,
- destination, selectedImageUri, sourceImageUri, flatten, 90, 1f, true);
+ destination, selectedImageUri, sourceImageUri, flatten, 90, scaleFactor, true);
filterShowActivity.startService(processIntent);
@@ -595,7 +635,7 @@ public class SaveImage {
* @return The file object. Return null if srcUri is invalid or not a local
* file.
*/
- private static File getLocalFileFromUri(Context context, Uri srcUri) {
+ public static File getLocalFileFromUri(Context context, Uri srcUri) {
if (srcUri == null) {
Log.e(LOGTAG, "srcUri is null.");
return null;
@@ -615,13 +655,13 @@ public class SaveImage {
querySource(context, srcUri, new String[] {
ImageColumns.DATA
},
- new ContentResolverQueryCallback() {
+ new ContentResolverQueryCallback() {
- @Override
- public void onCursorResult(Cursor cursor) {
- file[0] = new File(cursor.getString(0));
- }
- });
+ @Override
+ public void onCursorResult(Cursor cursor) {
+ file[0] = new File(cursor.getString(0));
+ }
+ });
}
} else if (scheme.equals(ContentResolver.SCHEME_FILE)) {
file[0] = new File(srcUri.getPath());
@@ -695,7 +735,7 @@ public class SaveImage {
}
private static ContentValues getContentValues(Context context, Uri sourceUri,
- File file, long time) {
+ File file, long time) {
final ContentValues values = new ContentValues();
time /= 1000;
@@ -720,20 +760,20 @@ public class SaveImage {
SaveImage.querySource(context, sourceUri, projection,
new ContentResolverQueryCallback() {
- @Override
- public void onCursorResult(Cursor cursor) {
- values.put(Images.Media.DATE_TAKEN, cursor.getLong(0));
-
- double latitude = cursor.getDouble(1);
- double longitude = cursor.getDouble(2);
- // TODO: Change || to && after the default location
- // issue is fixed.
- if ((latitude != 0f) || (longitude != 0f)) {
- values.put(Images.Media.LATITUDE, latitude);
- values.put(Images.Media.LONGITUDE, longitude);
- }
- }
- });
+ @Override
+ public void onCursorResult(Cursor cursor) {
+ values.put(Images.Media.DATE_TAKEN, cursor.getLong(0));
+
+ double latitude = cursor.getDouble(1);
+ double longitude = cursor.getDouble(2);
+ // TODO: Change || to && after the default location
+ // issue is fixed.
+ if ((latitude != 0f) || (longitude != 0f)) {
+ values.put(Images.Media.LATITUDE, latitude);
+ values.put(Images.Media.LONGITUDE, longitude);
+ }
+ }
+ });
return values;
}
diff --git a/src/com/android/gallery3d/mpo/MpoHeader.java b/src/com/android/gallery3d/mpo/MpoHeader.java
new file mode 100644
index 000000000..de8b9be49
--- /dev/null
+++ b/src/com/android/gallery3d/mpo/MpoHeader.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.mpo;
+
+class MpoHeader {
+ public static final short SOI = (short) 0xFFD8;
+ public static final short APP2 = (short) 0xFFE2;
+ public static final short APP1 = (short) 0xFFE1;
+ public static final short APP0 = (short) 0xFFE0;
+ public static final short EOI = (short) 0xFFD9;
+
+ /**
+ * SOF (start of frame). All value between SOF0 and SOF15 is SOF marker except for DHT, JPG,
+ * and DAC marker.
+ */
+ public static final short SOF0 = (short) 0xFFC0;
+ public static final short SOF15 = (short) 0xFFCF;
+ public static final short DHT = (short) 0xFFC4;
+ public static final short JPG = (short) 0xFFC8;
+ public static final short DAC = (short) 0xFFCC;
+
+ public static final int APP2_FIELD_LENGTH_BYTES = 2;
+ public static final int MP_FORMAT_IDENTIFIER_BYTES = 4;
+
+ public static final boolean isSofMarker(short marker) {
+ return marker >= SOF0 && marker <= SOF15 && marker != DHT && marker != JPG
+ && marker != DAC;
+ }
+}
diff --git a/src/com/android/gallery3d/mpo/MpoParser.java b/src/com/android/gallery3d/mpo/MpoParser.java
new file mode 100644
index 000000000..d859c05b4
--- /dev/null
+++ b/src/com/android/gallery3d/mpo/MpoParser.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.mpo;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.exif.CountedDataInputStream;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class MpoParser {
+ private static final String LOGTAG = "MpoParser";
+ private static final int MP_INDEX_FIELD_SIZE_BYTES = 12;
+
+ protected static final short LITTLE_ENDIAN_TAG = 0x4949; // "II"
+ protected static final short BIG_ENDIAN_TAG = 0x4d4d; // "MM"
+
+ private ContentResolver mContentResolver;
+ private Uri mUri;
+
+ private CountedDataInputStream mDataStream;
+ private ByteOrder mByteOrder;
+ private int mMpHeaderOffset;
+ private int mIfd1Offset;
+ private int mMpEntryOffset;
+ private MpEntry mPrimaryEntry;
+ private MpEntry mSecondaryEntry;
+
+ private MpoParser(Context context, Uri uri) {
+ mContentResolver = context.getContentResolver();
+ mUri = uri;
+
+ InputStream is = null;
+ try {
+ is = mContentResolver.openInputStream(mUri);
+ // seek to mp header
+ if((mMpHeaderOffset = seekToMpData(is)) == -1)
+ return;
+
+ // read mp header
+ mDataStream = new CountedDataInputStream(is);
+ readMpHeader();
+
+ // read mp index ifd
+ readMpIndexIfdData();
+
+ // read mp entries
+ readMpEntryData();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ Utils.closeSilently(is);
+ }
+ }
+
+ public static MpoParser parse(Context context, Uri uri) {
+ return new MpoParser(context, uri);
+ }
+
+ private int seekToMpData(InputStream inputStream) throws IOException {
+ CountedDataInputStream dataStream = new CountedDataInputStream(inputStream);
+ if (dataStream.readShort() != MpoHeader.SOI) {
+ return -1;
+ }
+
+ short marker = dataStream.readShort();
+ while (marker != MpoHeader.EOI
+ && !MpoHeader.isSofMarker(marker)) {
+ int length = dataStream.readUnsignedShort();
+ if (marker == MpoHeader.APP2) {
+ dataStream.readInt(); // MP Format Identifier
+ return dataStream.getReadByteCount();
+ }
+ if (length < 2 || (length - 2) != dataStream.skip(length - 2)) {
+ Log.w(LOGTAG, "Invalid JPEG format.");
+ return -1;
+ }
+ marker = dataStream.readShort();
+ }
+ return -1;
+ }
+
+ private void readMpHeader() throws IOException {
+ short byteOrder = mDataStream.readShort();
+ mByteOrder = (byteOrder == LITTLE_ENDIAN_TAG)?ByteOrder.LITTLE_ENDIAN:ByteOrder.BIG_ENDIAN;
+ mDataStream.setByteOrder(mByteOrder);
+ if(mDataStream.readShort() == 42) {
+ Log.v(LOGTAG, "correct endian!");
+ } else {
+ Log.w(LOGTAG, "incorrect endian!");
+ }
+
+ mIfd1Offset = mDataStream.readInt();
+ }
+
+ private void readMpIndexIfdData() throws IOException {
+ mDataStream.skipTo(mIfd1Offset);
+ int count = mDataStream.readShort();
+ // add 6 (2 for count, 4 for offset to next IFD)
+ mMpEntryOffset = mIfd1Offset + (count*MP_INDEX_FIELD_SIZE_BYTES) + 6;
+ }
+
+ private MpEntry readMpEntryData() {
+ try {
+ mDataStream.skipTo(mMpEntryOffset);
+
+ mPrimaryEntry = new MpEntry();
+ mPrimaryEntry.mImgAttribute = mDataStream.readInt();
+ mPrimaryEntry.mImgSize = mDataStream.readInt();
+ mPrimaryEntry.mImgDataOffset = mDataStream.readInt();
+ mPrimaryEntry.mDepImg1Entry = mDataStream.readShort();
+ mPrimaryEntry.mDepImg2Entry = mDataStream.readShort();
+
+ mSecondaryEntry = new MpEntry();
+ mSecondaryEntry.mImgAttribute = mDataStream.readInt();
+ mSecondaryEntry.mImgSize = mDataStream.readInt();
+ mSecondaryEntry.mImgDataOffset = mDataStream.readInt();
+ mSecondaryEntry.mDepImg1Entry = mDataStream.readShort();
+ mSecondaryEntry.mDepImg2Entry = mDataStream.readShort();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return mPrimaryEntry;
+ }
+
+ public byte[] readImgData(boolean primary) {
+ MpEntry mpEntry = null;
+ byte[] data = null;
+
+ if(primary) {
+ mpEntry = mPrimaryEntry;
+ } else {
+ mpEntry = mSecondaryEntry;
+ }
+
+ if(mpEntry == null)
+ return data;
+
+ InputStream is = null;
+ ByteArrayOutputStream baos = null;
+ try {
+ is = mContentResolver.openInputStream(mUri);
+ data = new byte[mpEntry.mImgSize];
+
+ is.skip((mpEntry.mImgDataOffset>0)?mpEntry.mImgDataOffset + mMpHeaderOffset : mpEntry.mImgDataOffset);
+ if(is.read(data) == -1) {
+ Log.d(LOGTAG, "read EOF. invalid offset/size");
+ data = null;
+ } else {
+ // verify we have well formed jpeg data
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ if(buffer.getShort(0) != MpoHeader.SOI) {
+ Log.d(LOGTAG, "non valid SOI. offset incorrect.");
+ data = null;
+ } else if(buffer.getShort(buffer.limit() - 2) != MpoHeader.EOI) {
+ Log.d(LOGTAG, "non valid EOI. size incorrect. attempting to read further till EOI");
+ baos = new ByteArrayOutputStream(data.length);
+ baos.write(data);
+
+ byte[] readArray = new byte[2];
+ ByteBuffer readBuf = ByteBuffer.wrap(readArray);
+
+ readArray[0] = data[data.length-2];
+ readArray[1] = data[data.length-1];
+
+ data = null;
+
+ boolean validJpg = true;
+ while(readBuf.getShort(0) != MpoHeader.EOI) {
+ int read = is.read();
+ if(read == -1) {
+ Log.d(LOGTAG, "reached EOF before EOI. invalid file");
+ validJpg = false;
+ break;
+ }
+ readArray[0] = readArray[1];
+ readArray[1] = (byte) (read & 0xFF);
+
+ baos.write(read);
+ }
+
+ if(validJpg)
+ data = baos.toByteArray();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ Utils.closeSilently(is);
+ Utils.closeSilently(baos);
+ }
+
+ return data;
+ }
+
+ public static String getDepthmapFilepath(String mpoFilepath) {
+ String depthFilepath = mpoFilepath.substring(0, mpoFilepath.lastIndexOf('.'))
+ + DualCameraNativeEngine.DEPTH_MAP_EXT;
+
+ return depthFilepath;
+ }
+
+ public static void writeDepthMapFile(String depthMapFilepath, ByteBuffer depthMap) {
+ FileChannel fc = null;
+ try {
+ fc = new FileOutputStream(depthMapFilepath).getChannel();
+ fc.write(depthMap);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if(fc != null) {
+ try {
+ fc.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ depthMap.clear();
+ }
+
+ public static ByteBuffer readDepthMapFile(String depthMapFilepath) {
+ FileChannel fc = null;
+ ByteBuffer depthMap = null;
+ try {
+ fc = new FileInputStream(depthMapFilepath).getChannel();
+ depthMap = ByteBuffer.allocateDirect((int)fc.size());
+ fc.read(depthMap);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if(fc != null) {
+ try {
+ fc.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return depthMap;
+ }
+
+ class MpEntry {
+ int mImgAttribute;
+ int mImgSize;
+ int mImgDataOffset;
+ short mDepImg1Entry;
+ short mDepImg2Entry;
+ }
+} \ No newline at end of file