summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-01-18 02:29:07 -0800
committerLinux Build Service Account <lnxbuild@localhost>2017-01-18 02:29:08 -0800
commit04ac0bdc56b421a3a64980403b4edeefb6ddf6d3 (patch)
tree9d07356686b0819e213abe5df30b8e2693242dba
parentbb2054566a7ab88cf34c0ab73d4cfcb9af014ca7 (diff)
parentf4cfa24e62dc4278c5b0f168339c98ceb28b41fa (diff)
downloadandroid_packages_apps_Gallery2-04ac0bdc56b421a3a64980403b4edeefb6ddf6d3.tar.gz
android_packages_apps_Gallery2-04ac0bdc56b421a3a64980403b4edeefb6ddf6d3.tar.bz2
android_packages_apps_Gallery2-04ac0bdc56b421a3a64980403b4edeefb6ddf6d3.zip
Promotion of android_ui.lnx.2.1.c1-00031.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1104597 I394861b022ee03c709d9a95ae9cf211a92c81004 Gallery: fix ddm effect not applied on complete image 1098120 Ia185f8bac84152cce44cb4f99c48dfe1ae97038b SnapdragonGallery: Fix trueportraint crash. 1088828 1090568 Ib46c6c336b4bfc4e403e457aa672404d7dc7c561 Galley: add DDM feature code Change-Id: I9c3c623844472e60b0bb4f208839554a09a54d32 CRs-Fixed: 1098120, 1088828, 1104597, 1090568
-rwxr-xr-xAndroidManifest.xml1
-rwxr-xr-xres/drawable-hdpi/blackboard.pngbin0 -> 12231 bytes
-rwxr-xr-xres/drawable-hdpi/bw.pngbin0 -> 13812 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-hdpi/focus.pngbin15562 -> 13753 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-hdpi/fusion.pngbin22420 -> 18830 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-hdpi/halo.pngbin18272 -> 19538 bytes
-rwxr-xr-xres/drawable-hdpi/motion.pngbin0 -> 13189 bytes
-rwxr-xr-xres/drawable-hdpi/negative.pngbin0 -> 19656 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-hdpi/none.pngbin16866 -> 19608 bytes
-rwxr-xr-xres/drawable-hdpi/posterize.pngbin0 -> 16930 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-hdpi/sketch.pngbin23417 -> 14844 bytes
-rwxr-xr-xres/drawable-hdpi/whiteboard.pngbin0 -> 13018 bytes
-rwxr-xr-xres/drawable-hdpi/zoom.pngbin0 -> 17337 bytes
-rwxr-xr-xres/drawable-xhdpi/blackboard.pngbin0 -> 24610 bytes
-rwxr-xr-xres/drawable-xhdpi/bw.pngbin0 -> 30239 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xhdpi/focus.pngbin23754 -> 27291 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xhdpi/fusion.pngbin36951 -> 40890 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xhdpi/halo.pngbin30310 -> 44186 bytes
-rwxr-xr-xres/drawable-xhdpi/motion.pngbin0 -> 27015 bytes
-rwxr-xr-xres/drawable-xhdpi/negative.pngbin0 -> 44515 bytes
-rwxr-xr-xres/drawable-xhdpi/none.pngbin0 -> 44479 bytes
-rwxr-xr-xres/drawable-xhdpi/posterize.pngbin0 -> 37259 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xhdpi/sketch.pngbin40439 -> 32652 bytes
-rwxr-xr-xres/drawable-xhdpi/three_d.pngbin0 -> 2639 bytes
-rwxr-xr-xres/drawable-xhdpi/whiteboard.pngbin0 -> 26494 bytes
-rwxr-xr-xres/drawable-xhdpi/zoom.pngbin0 -> 37610 bytes
-rwxr-xr-xres/drawable-xxhdpi/blackboard.pngbin0 -> 37472 bytes
-rwxr-xr-xres/drawable-xxhdpi/bw.pngbin0 -> 52504 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xxhdpi/focus.pngbin49557 -> 43738 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xxhdpi/fusion.pngbin84358 -> 69500 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xxhdpi/halo.pngbin68562 -> 77915 bytes
-rwxr-xr-xres/drawable-xxhdpi/motion.pngbin0 -> 43611 bytes
-rwxr-xr-xres/drawable-xxhdpi/negative.pngbin0 -> 78232 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xxhdpi/none.pngbin63931 -> 78603 bytes
-rwxr-xr-xres/drawable-xxhdpi/posterize.pngbin0 -> 63763 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xxhdpi/sketch.pngbin113272 -> 56448 bytes
-rwxr-xr-xres/drawable-xxhdpi/three_d.pngbin0 -> 5794 bytes
-rwxr-xr-xres/drawable-xxhdpi/whiteboard.pngbin0 -> 38273 bytes
-rwxr-xr-xres/drawable-xxhdpi/zoom.pngbin0 -> 63260 bytes
-rwxr-xr-xres/layout/activity_three_dimensional.xml74
-rwxr-xr-xres/layout/filtershow_actionbar_dualcam_fusion.xml45
-rwxr-xr-xres/layout/three_d_button.xml52
-rwxr-xr-xres/values-zh-rCN/filtershow_strings.xml24
-rwxr-xr-x[-rw-r--r--]res/values/filtershow_strings.xml20
-rwxr-xr-xsrc/com/android/gallery3d/app/GalleryActivity.java3
-rwxr-xr-xsrc/com/android/gallery3d/app/PhotoPage.java101
-rwxr-xr-xsrc/com/android/gallery3d/app/ThreeDButton.java109
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/Effect.java211
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/GLView.java186
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java183
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/gl/Error.java44
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/gl/Mesh.java149
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/gl/Renderer.java178
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/gl/Settings.java47
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/gl/Shader.java105
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/gl/Texture.java65
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/mpo/Task.java241
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/threed/Controller.java178
-rwxr-xr-xsrc/com/android/gallery3d/app/dualcam3d/threed/Gyro.java115
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/FilterShowActivity.java36
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/category/MainPanel.java24
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java189
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java6
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java57
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java12
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java43
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java41
-rwxr-xr-xsrc/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java2
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java4
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/filtershow/imageshow/MasterImage.java13
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java62
-rw-r--r--src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java25
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/mpo/MpoParser.java71
73 files changed, 2622 insertions, 94 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index bfdd8f77a..0e6b42966 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -399,5 +399,6 @@
android:theme="@android:style/Theme.Material.Light"
android:configChanges="orientation|keyboardHidden|screenSize|mnc|mcc">
</activity>
+ <activity android:name="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity"/>
</application>
</manifest>
diff --git a/res/drawable-hdpi/blackboard.png b/res/drawable-hdpi/blackboard.png
new file mode 100755
index 000000000..6cb6e31d4
--- /dev/null
+++ b/res/drawable-hdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-hdpi/bw.png b/res/drawable-hdpi/bw.png
new file mode 100755
index 000000000..fa8175473
--- /dev/null
+++ b/res/drawable-hdpi/bw.png
Binary files differ
diff --git a/res/drawable-hdpi/focus.png b/res/drawable-hdpi/focus.png
index a168a05d0..64eb95fa2 100644..100755
--- a/res/drawable-hdpi/focus.png
+++ b/res/drawable-hdpi/focus.png
Binary files differ
diff --git a/res/drawable-hdpi/fusion.png b/res/drawable-hdpi/fusion.png
index 7abeb245f..52438ae8e 100644..100755
--- a/res/drawable-hdpi/fusion.png
+++ b/res/drawable-hdpi/fusion.png
Binary files differ
diff --git a/res/drawable-hdpi/halo.png b/res/drawable-hdpi/halo.png
index f32da8519..35a462056 100644..100755
--- a/res/drawable-hdpi/halo.png
+++ b/res/drawable-hdpi/halo.png
Binary files differ
diff --git a/res/drawable-hdpi/motion.png b/res/drawable-hdpi/motion.png
new file mode 100755
index 000000000..1a03479a2
--- /dev/null
+++ b/res/drawable-hdpi/motion.png
Binary files differ
diff --git a/res/drawable-hdpi/negative.png b/res/drawable-hdpi/negative.png
new file mode 100755
index 000000000..b4989d4af
--- /dev/null
+++ b/res/drawable-hdpi/negative.png
Binary files differ
diff --git a/res/drawable-hdpi/none.png b/res/drawable-hdpi/none.png
index 58a7fd833..107b299b3 100644..100755
--- a/res/drawable-hdpi/none.png
+++ b/res/drawable-hdpi/none.png
Binary files differ
diff --git a/res/drawable-hdpi/posterize.png b/res/drawable-hdpi/posterize.png
new file mode 100755
index 000000000..042b686c1
--- /dev/null
+++ b/res/drawable-hdpi/posterize.png
Binary files differ
diff --git a/res/drawable-hdpi/sketch.png b/res/drawable-hdpi/sketch.png
index f43f6ace1..e1603a9b7 100644..100755
--- a/res/drawable-hdpi/sketch.png
+++ b/res/drawable-hdpi/sketch.png
Binary files differ
diff --git a/res/drawable-hdpi/whiteboard.png b/res/drawable-hdpi/whiteboard.png
new file mode 100755
index 000000000..584da40a1
--- /dev/null
+++ b/res/drawable-hdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-hdpi/zoom.png b/res/drawable-hdpi/zoom.png
new file mode 100755
index 000000000..ea1211f29
--- /dev/null
+++ b/res/drawable-hdpi/zoom.png
Binary files differ
diff --git a/res/drawable-xhdpi/blackboard.png b/res/drawable-xhdpi/blackboard.png
new file mode 100755
index 000000000..287a6f717
--- /dev/null
+++ b/res/drawable-xhdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-xhdpi/bw.png b/res/drawable-xhdpi/bw.png
new file mode 100755
index 000000000..d0052d162
--- /dev/null
+++ b/res/drawable-xhdpi/bw.png
Binary files differ
diff --git a/res/drawable-xhdpi/focus.png b/res/drawable-xhdpi/focus.png
index ea695b49c..c58f4c674 100644..100755
--- a/res/drawable-xhdpi/focus.png
+++ b/res/drawable-xhdpi/focus.png
Binary files differ
diff --git a/res/drawable-xhdpi/fusion.png b/res/drawable-xhdpi/fusion.png
index 158fcbb2e..625eb85c3 100644..100755
--- a/res/drawable-xhdpi/fusion.png
+++ b/res/drawable-xhdpi/fusion.png
Binary files differ
diff --git a/res/drawable-xhdpi/halo.png b/res/drawable-xhdpi/halo.png
index 8047a73e1..93846175d 100644..100755
--- a/res/drawable-xhdpi/halo.png
+++ b/res/drawable-xhdpi/halo.png
Binary files differ
diff --git a/res/drawable-xhdpi/motion.png b/res/drawable-xhdpi/motion.png
new file mode 100755
index 000000000..7d2b8a6ba
--- /dev/null
+++ b/res/drawable-xhdpi/motion.png
Binary files differ
diff --git a/res/drawable-xhdpi/negative.png b/res/drawable-xhdpi/negative.png
new file mode 100755
index 000000000..a1eab0da7
--- /dev/null
+++ b/res/drawable-xhdpi/negative.png
Binary files differ
diff --git a/res/drawable-xhdpi/none.png b/res/drawable-xhdpi/none.png
new file mode 100755
index 000000000..703556222
--- /dev/null
+++ b/res/drawable-xhdpi/none.png
Binary files differ
diff --git a/res/drawable-xhdpi/posterize.png b/res/drawable-xhdpi/posterize.png
new file mode 100755
index 000000000..157ad30e3
--- /dev/null
+++ b/res/drawable-xhdpi/posterize.png
Binary files differ
diff --git a/res/drawable-xhdpi/sketch.png b/res/drawable-xhdpi/sketch.png
index 357cb4176..f4fc6eb82 100644..100755
--- a/res/drawable-xhdpi/sketch.png
+++ b/res/drawable-xhdpi/sketch.png
Binary files differ
diff --git a/res/drawable-xhdpi/three_d.png b/res/drawable-xhdpi/three_d.png
new file mode 100755
index 000000000..ab8d4df54
--- /dev/null
+++ b/res/drawable-xhdpi/three_d.png
Binary files differ
diff --git a/res/drawable-xhdpi/whiteboard.png b/res/drawable-xhdpi/whiteboard.png
new file mode 100755
index 000000000..1225d335f
--- /dev/null
+++ b/res/drawable-xhdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-xhdpi/zoom.png b/res/drawable-xhdpi/zoom.png
new file mode 100755
index 000000000..f3eac3d73
--- /dev/null
+++ b/res/drawable-xhdpi/zoom.png
Binary files differ
diff --git a/res/drawable-xxhdpi/blackboard.png b/res/drawable-xxhdpi/blackboard.png
new file mode 100755
index 000000000..0881d3b4c
--- /dev/null
+++ b/res/drawable-xxhdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-xxhdpi/bw.png b/res/drawable-xxhdpi/bw.png
new file mode 100755
index 000000000..a2accdd11
--- /dev/null
+++ b/res/drawable-xxhdpi/bw.png
Binary files differ
diff --git a/res/drawable-xxhdpi/focus.png b/res/drawable-xxhdpi/focus.png
index 8d58fd6ce..15bb4a415 100644..100755
--- a/res/drawable-xxhdpi/focus.png
+++ b/res/drawable-xxhdpi/focus.png
Binary files differ
diff --git a/res/drawable-xxhdpi/fusion.png b/res/drawable-xxhdpi/fusion.png
index 1e88b9b6b..8bd69e348 100644..100755
--- a/res/drawable-xxhdpi/fusion.png
+++ b/res/drawable-xxhdpi/fusion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/halo.png b/res/drawable-xxhdpi/halo.png
index 99ed56f6c..d3a69f9e4 100644..100755
--- a/res/drawable-xxhdpi/halo.png
+++ b/res/drawable-xxhdpi/halo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/motion.png b/res/drawable-xxhdpi/motion.png
new file mode 100755
index 000000000..7eb4c2cff
--- /dev/null
+++ b/res/drawable-xxhdpi/motion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/negative.png b/res/drawable-xxhdpi/negative.png
new file mode 100755
index 000000000..90a609fd0
--- /dev/null
+++ b/res/drawable-xxhdpi/negative.png
Binary files differ
diff --git a/res/drawable-xxhdpi/none.png b/res/drawable-xxhdpi/none.png
index 6e54e7d59..74e451920 100644..100755
--- a/res/drawable-xxhdpi/none.png
+++ b/res/drawable-xxhdpi/none.png
Binary files differ
diff --git a/res/drawable-xxhdpi/posterize.png b/res/drawable-xxhdpi/posterize.png
new file mode 100755
index 000000000..0bc95dffc
--- /dev/null
+++ b/res/drawable-xxhdpi/posterize.png
Binary files differ
diff --git a/res/drawable-xxhdpi/sketch.png b/res/drawable-xxhdpi/sketch.png
index be89c59a0..22931feaa 100644..100755
--- a/res/drawable-xxhdpi/sketch.png
+++ b/res/drawable-xxhdpi/sketch.png
Binary files differ
diff --git a/res/drawable-xxhdpi/three_d.png b/res/drawable-xxhdpi/three_d.png
new file mode 100755
index 000000000..ab58b4553
--- /dev/null
+++ b/res/drawable-xxhdpi/three_d.png
Binary files differ
diff --git a/res/drawable-xxhdpi/whiteboard.png b/res/drawable-xxhdpi/whiteboard.png
new file mode 100755
index 000000000..f584c3fce
--- /dev/null
+++ b/res/drawable-xxhdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-xxhdpi/zoom.png b/res/drawable-xxhdpi/zoom.png
new file mode 100755
index 000000000..2c1dd02da
--- /dev/null
+++ b/res/drawable-xxhdpi/zoom.png
Binary files differ
diff --git a/res/layout/activity_three_dimensional.xml b/res/layout/activity_three_dimensional.xml
new file mode 100755
index 000000000..316c9ad71
--- /dev/null
+++ b/res/layout/activity_three_dimensional.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity">
+
+ <include layout="@layout/three_d_button" />
+
+ <com.android.gallery3d.app.dualcam3d.GLView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <LinearLayout
+ android:id="@+id/mode_3d"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ android:orientation="vertical"
+ android:visibility="gone">
+
+ <Button
+ android:id="@+id/mode_gyro"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:text="@string/grad"
+ android:textAlignment="center" />
+
+ <Button
+ android:id="@+id/mode_auto"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:text="@string/auto"
+ android:textAlignment="center" />
+
+ <Button
+ android:id="@+id/mode_touch"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:text="@string/trueportrait_touch_up"
+ android:textAlignment="center" />
+ </LinearLayout>
+
+</merge>
diff --git a/res/layout/filtershow_actionbar_dualcam_fusion.xml b/res/layout/filtershow_actionbar_dualcam_fusion.xml
new file mode 100755
index 000000000..c5cec2572
--- /dev/null
+++ b/res/layout/filtershow_actionbar_dualcam_fusion.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright (c) 2016, 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+
+ <ImageButton
+ android:id="@+id/pick_underlay"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:background="@android:color/transparent"
+ android:paddingEnd="16dp"
+ android:paddingStart="16dp"
+ android:src="@drawable/tp_bg_select" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/three_d_button.xml b/res/layout/three_d_button.xml
new file mode 100755
index 000000000..eb8366db3
--- /dev/null
+++ b/res/layout/three_d_button.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/three_d_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="100dp"
+ android:layout_marginEnd="50dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentEnd="true"
+ android:layout_gravity="bottom"
+ android:orientation="horizontal"
+ android:theme="@android:style/Theme.DeviceDefault"
+ android:visibility="gone">
+
+ <ImageButton
+ android:id="@+id/three_dimensional"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:background="?android:attr/actionBarItemBackground"
+ android:src="@drawable/three_d"
+ android:visibility="visible" />
+</LinearLayout>
diff --git a/res/values-zh-rCN/filtershow_strings.xml b/res/values-zh-rCN/filtershow_strings.xml
index 3d73589bf..0c372c2e1 100755
--- a/res/values-zh-rCN/filtershow_strings.xml
+++ b/res/values-zh-rCN/filtershow_strings.xml
@@ -154,9 +154,33 @@
<string name="filtershow_exif_f_stop" msgid="6081797865604483139">"光圈值"</string>
<string name="filtershow_exif_exposure_time" msgid="4099067062781294115">"曝光时间"</string>
<string name="filtershow_exif_copyright" msgid="8801875918803737581">"版权"</string>
+ <!-- Label for the "refocus" dual camera effect [CHAR LIMIT=15] -->
+ <string name="focus">对焦</string>
+ <!-- Label for the "fusion" dual camera effect [CHAR LIMIT=15] -->
+ <string name="fusion">背景切换</string>
+ <!-- Label for the "sketch" dual camera effect [CHAR LIMIT=15] -->
+ <string name="sketch">素描</string>
+ <!-- Label for the "halo" dual camera effect [CHAR LIMIT=15] -->
+ <string name="halo">光环</string>
+ <!-- Label for the "zoom" dual camera effect [CHAR LIMIT=15] -->
+ <string name="zoom">缩放模糊</string>
+ <!-- Label for the "motion" dual camera effect [CHAR LIMIT=15] -->
+ <string name="motion">动态模糊</string>
+ <!-- Label for the "bw" dual camera effect [CHAR LIMIT=15] -->
+ <string name="bw">去色</string>
+ <!-- Label for the "blackboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="blackboard">黑板</string>
+ <!-- Label for the "whiteboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="whiteboard">白板</string>
+ <!-- Label for the "posterize" dual camera effect [CHAR LIMIT=15] -->
+ <string name="posterize">色块化</string>
+ <!-- Label for the "negative" dual camera effect [CHAR LIMIT=15] -->
+ <string name="dc_negative">负片</string>
<string name="color">滤镜</string>
<string name="frames">相框</string>
+ <string name="dual_camera_effects">双摄像头效果</string>
+ <string name="dual_camera_effects_intro">此功能可将双摄像头效果应用到背景上,如动态模糊和素描。.你可以将两张照片合并到一起来创建一个有趣的效果。这个功能在你的摄像头和照片的主体有一个短距离时效果最好。</string>
<string name="trueportrait_intro">此功能用于增强人像照。你可以将效果应用于照片背景,例如“模糊”和“速写”。你也可以将两张照片拼在一起来给你的人像照创建一个有趣的背景。</string>
</resources>
diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml
index 7c0212e7e..bdf5acebd 100644..100755
--- a/res/values/filtershow_strings.xml
+++ b/res/values/filtershow_strings.xml
@@ -208,6 +208,20 @@
<string name="sketch">Sketch</string>
<!-- Label for the "halo" dual camera effect [CHAR LIMIT=15] -->
<string name="halo">Halo</string>
+ <!-- Label for the "zoom" dual camera effect [CHAR LIMIT=15] -->
+ <string name="zoom">Zoom</string>
+ <!-- Label for the "motion" dual camera effect [CHAR LIMIT=15] -->
+ <string name="motion">Motion</string>
+ <!-- Label for the "bw" dual camera effect [CHAR LIMIT=15] -->
+ <string name="bw">B/W</string>
+ <!-- Label for the "blackboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="blackboard">Blackboard</string>
+ <!-- Label for the "whiteboard" dual camera effect [CHAR LIMIT=15] -->
+ <string name="whiteboard">Whiteboard</string>
+ <!-- Label for the "posterize" dual camera effect [CHAR LIMIT=15] -->
+ <string name="posterize">Posterize</string>
+ <!-- Label for the "negative" dual camera effect [CHAR LIMIT=15] -->
+ <string name="dc_negative">negative</string>
<!-- Label for the "blur" true portrait effect [CHAR LIMIT=15] -->
<string name="blur">Blur</string>
<!-- Label for the "motion blur" true portrait effect [CHAR LIMIT=15] -->
@@ -350,6 +364,8 @@
<string name="fusion_pick_point">Pick Segment</string>
<string name="fusion_pick_underlay">Pick Underlay</string>
+ <string name="dual_camera_effects">Dual Camera Effects</string>
+ <string name="dual_camera_effects_intro">Allows you to apply background effects, such as "Motion" and "Sketch". You can also merge two photos together for interesting effects. This feature works best when you have a short distance your camera and the main subject of you picture.</string>
<string name="dualcam_no_segment_toast">No segment found at this point</string>
<string name="dualcam_filter_not_supported">Dual camera filters not supported for this image</string>
<string name="trueportrait_intro">Allows you to enhance photos of people. You can apply effects to the background, such as \"blur\" and \"sketch\". You can also merge two photos together to create interesting backgrounds for your portrait photos.</string>
@@ -359,6 +375,7 @@
<string name="trueportrait_edit_background_toast">Use your finger to paint in any areas of the background that were missed.</string>
<string name="trueportrait_edit_help">To zoom, use two fingers to pinch open or closed. You can also drag with two fingers to re-position the image. This can make it easier to fix any problem areas.</string>
<string name="trueportrait_fusion_intro">Your foreground person can be copied and pasted onto any photo in your Gallery. You can try using different background photos to create new and interesting portraits.</string>
+ <string name="dualcam_fusion_intro">Your foreground can be copied and pasted onto any photo in your Gallery. \n\nYou can try using different background photos to create new and interesting portraits.</string>
<string name="do_not_show_again">Do not show again</string>
<string name="trueportrait_touch_up">Touch Up</string>
<string name="fusion_pick_background">Select Background Photo</string>
@@ -372,8 +389,11 @@
<string name="background">Background</string>
<string name="brush_size">Brush Size</string>
+ <string name="pref_dualcam_intro_show_key" translatable="false">pref_dualcam_intro_show_key</string>
<string name="pref_trueportrait_intro_show_key" translatable="false">pref_trueportrait_intro_show_key</string>
<string name="pref_trueportrait_edit_intro_show_key" translatable="false">pref_trueportrait_edit_intro_show_key</string>
<string name="pref_trueportrait_fusion_intro_show_key" translatable="false">pref_trueportrait_fusion_intro_show_key</string>
<string name="pref_trueportrait_fusion_underlay_key" translatable="false">pref_trueportrait_fusion_underlay_key</string>
+ <string name="pref_dualcam_fusion_underlay_key" translatable="false">pref_dualcam_fusion_underlay_key</string>
+ <string name="pref_dualcam_fusion_intro_show_key" translatable="false">pref_trueportrait_fusion_intro_show_key</string>
</resources>
diff --git a/src/com/android/gallery3d/app/GalleryActivity.java b/src/com/android/gallery3d/app/GalleryActivity.java
index e18f1c2c6..bdcc0c6b4 100755
--- a/src/com/android/gallery3d/app/GalleryActivity.java
+++ b/src/com/android/gallery3d/app/GalleryActivity.java
@@ -750,7 +750,8 @@ public final class GalleryActivity extends AbstractGalleryActivity implements On
DualCameraNativeEngine.getInstance().initDepthMap(
primaryBm, auxiliaryBm, mpoFilepath,
- DualCameraNativeEngine.getInstance().getCalibFilepath(context));
+ DualCameraNativeEngine.getInstance().getCalibFilepath(context),
+ DualCameraNativeEngine.DEFAULT_BRIGHTNESS_INTENSITY);
primaryBm.recycle();
primaryBm = null;
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index 161d729da..8cea64ea5 100755
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -30,6 +30,7 @@ import android.net.Uri;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateBeamUrisCallback;
import android.nfc.NfcEvent;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -47,6 +48,8 @@ import android.widget.Toast;
import android.widget.Toolbar;
import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.data.ComboAlbum;
import com.android.gallery3d.data.DataManager;
@@ -64,6 +67,8 @@ import com.android.gallery3d.data.SnailAlbum;
import com.android.gallery3d.data.SnailItem;
import com.android.gallery3d.data.SnailSource;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.mpo.MpoParser;
import com.android.gallery3d.ui.DetailsHelper;
import com.android.gallery3d.ui.DetailsHelper.CloseListener;
import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
@@ -83,7 +88,7 @@ import java.util.Locale;
public abstract class PhotoPage extends ActivityState implements
PhotoView.Listener, AppBridge.Server, ShareActionProvider.OnShareTargetSelectedListener,
- PhotoPageBottomControls.Delegate {
+ PhotoPageBottomControls.Delegate, ThreeDButton.Delegate{
private static final String TAG = "PhotoPage";
private static final int MSG_HIDE_BARS = 1;
@@ -208,6 +213,11 @@ public abstract class PhotoPage extends ActivityState implements
private int originalHeight = 0;
private int originalPadding = 0;
+ private ThreeDButton m3DButton;
+ private boolean bShow3DButton;
+ private LoadMpoDataTask mLoadMpoTask = new LoadMpoDataTask();;
+ private ParseMpoDataTask mParseMpoDateTask = new ParseMpoDataTask();
+
private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() {
@Override
public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
@@ -302,6 +312,9 @@ public abstract class PhotoPage extends ActivityState implements
mIsPanorama = message.arg1 == 1;
mIsPanorama360 = message.arg2 == 1;
mBottomControls.refresh();
+ if (null != m3DButton) {
+ m3DButton.refresh();
+ }
}
break;
}
@@ -591,6 +604,7 @@ public abstract class PhotoPage extends ActivityState implements
if (galleryRoot != null) {
if (mSecureAlbum == null) {
mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot);
+ m3DButton = new ThreeDButton(this, mActivity, galleryRoot);
}
}
@@ -690,6 +704,23 @@ public abstract class PhotoPage extends ActivityState implements
}
}
+ @Override
+ public boolean canDisplay3DButton() {
+ return bShow3DButton && mShowBars && !mPhotoView.getFilmMode();
+ }
+
+ @Override
+ public void on3DButtonClicked() {
+ if (mCurrentPhoto != null) {
+ Path p = mCurrentPhoto.getPath();
+ Uri uri = mActivity.getDataManager().getContentUri(p);
+ Intent intent = new Intent();
+ intent.setClass(mActivity, ThreeDimensionalActivity.class);
+ intent.setData(uri);
+ mActivity.startActivity(intent);
+ }
+ }
+
@TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
private void setupNfcBeamPush() {
if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) return;
@@ -828,6 +859,7 @@ public abstract class PhotoPage extends ActivityState implements
updateMenuOperations();
refreshBottomControlsWhenReady();
+ parseMpoData();
if (mShowDetails) {
mDetailsHelper.reloadDetails();
}
@@ -1419,6 +1451,7 @@ public abstract class PhotoPage extends ActivityState implements
}
if (null != mModel) {
mModel.setCurrentPhoto(path, mCurrentIndex);
+ parseMpoData();
}
}
}
@@ -1464,11 +1497,21 @@ public abstract class PhotoPage extends ActivityState implements
}
if (path != null) {
mModel.setCurrentPhoto(Path.fromString(path), index);
+ parseMpoData();
}
}
}
}
+ private void parseMpoData() {
+ bShow3DButton = false;
+ if (mParseMpoDateTask.getStatus() != AsyncTask.Status.FINISHED) {
+ boolean r = mParseMpoDateTask.cancel(true);
+ }
+ mParseMpoDateTask = new ParseMpoDataTask();
+ mParseMpoDateTask.execute();
+ }
+
@Override
public void onPause() {
super.onPause();
@@ -1663,6 +1706,7 @@ public abstract class PhotoPage extends ActivityState implements
}
mActivity.getGLRoot().setOrientationSource(null);
if (mBottomControls != null) mBottomControls.cleanup();
+ if (m3DButton != null) m3DButton.cleanup();
mPhotoView.destroy();
mPhotoView = null;
// Remove all pending messages.
@@ -1761,4 +1805,59 @@ public abstract class PhotoPage extends ActivityState implements
}
}
+ public class ParseMpoDataTask extends AsyncTask<Void, Void, Void> {
+ private byte[] mPrimaryImgData = null;
+ private byte[] mAuxImgData = null;
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ MpoParser parser = MpoParser.parse(mActivity, mCurrentPhoto.getContentUri());
+ mPrimaryImgData = parser.readImgData(true);
+ mAuxImgData = parser.readImgData(false);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ if (isCancelled()){
+ bShow3DButton = false;
+ m3DButton.refresh();
+ return;
+ }
+ if(mPrimaryImgData == null ||
+ mAuxImgData == null) {
+ // parse failed
+ bShow3DButton = false;
+ } else {
+ if (mLoadMpoTask.getStatus() != Status.FINISHED) {
+ boolean r = mLoadMpoTask.cancel(true);
+ }
+ bShow3DButton = true;
+ mLoadMpoTask = new LoadMpoDataTask();
+ mLoadMpoTask.execute(mPrimaryImgData, mAuxImgData);
+ }
+ m3DButton.refresh();
+ }
+ }
+
+ private class LoadMpoDataTask extends AsyncTask<byte[], Void, Boolean> {
+
+ @Override
+ protected Boolean doInBackground(byte[]... params) {
+ return MasterImage.getImage().loadMpo(mActivity, params[0], params[1], mCurrentPhoto.getContentUri());
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (isCancelled()){
+ bShow3DButton = false;
+ m3DButton.refresh();
+ return;
+ }
+ if (!result) {
+ bShow3DButton = result;
+ m3DButton.refresh();
+ }
+ }
+ }
}
diff --git a/src/com/android/gallery3d/app/ThreeDButton.java b/src/com/android/gallery3d/app/ThreeDButton.java
new file mode 100755
index 000000000..4cc146ab9
--- /dev/null
+++ b/src/com/android/gallery3d/app/ThreeDButton.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, 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.app;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.widget.RelativeLayout;
+
+import org.codeaurora.gallery.R;
+
+public class ThreeDButton implements OnClickListener {
+ interface Delegate {
+ boolean canDisplay3DButton();
+
+ void on3DButtonClicked();
+ }
+
+ private Delegate mDelegate;
+ private ViewGroup root;
+ private ViewGroup mContainer;
+ private boolean mContainerVisible = false;
+
+ private Animation mAnimIn = new AlphaAnimation(0f, 1f);
+ private Animation mAnimOut = new AlphaAnimation(1f, 0f);
+ private static final int ANIM_DURATION = 200;
+
+ public ThreeDButton(Delegate delegate, Context context, RelativeLayout layout) {
+ mDelegate = delegate;
+ root = layout;
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mContainer = (ViewGroup) inflater
+ .inflate(R.layout.three_d_button, root, false);
+ mContainer.findViewById(R.id.three_dimensional).setOnClickListener(this);
+ root.addView(mContainer);
+ mAnimIn.setDuration(ANIM_DURATION);
+ mAnimOut.setDuration(ANIM_DURATION);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mContainer.getVisibility() == View.VISIBLE) {
+ mDelegate.on3DButtonClicked();
+ }
+ }
+
+ public void refresh() {
+ boolean visible = mDelegate.canDisplay3DButton();
+ if (visible != mContainerVisible) {
+ if (visible) {
+ show();
+ } else {
+ hide();
+ }
+ mContainerVisible = visible;
+ }
+ }
+
+ private void hide() {
+ mContainer.clearAnimation();
+ mAnimOut.reset();
+ mContainer.startAnimation(mAnimOut);
+ mContainer.setVisibility(View.GONE);
+ }
+
+ private void show() {
+ mContainer.clearAnimation();
+ mAnimIn.reset();
+ mContainer.startAnimation(mAnimIn);
+ mContainer.setVisibility(View.VISIBLE);
+ }
+
+ public void cleanup() {
+ root.removeView(mContainer);
+ }
+
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/Effect.java b/src/com/android/gallery3d/app/dualcam3d/Effect.java
new file mode 100755
index 000000000..0f9cde4cb
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/Effect.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import com.android.gallery3d.app.dualcam3d.threed.Controller;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class Effect implements GLView.Listener {
+ private static final String TAG = "Effect";
+ public static final int INTENSITY_MAX = 10;
+ public static final float DEFAULT_BRIGHTNESS_INTENSITY = 1.0f;
+ private static final int PREVIEW_DIMENSION_MAX = 1080;
+
+ enum Type {
+ NONE, FOCUS, HALO, SKETCH, FUSION, ZOOM,
+ MOTION, BW, BLACKBOARD, WHITEBOARD,
+ POSTERIZE, NEGATIVE, THREE_DIMENSIONAL
+ }
+
+ private final ThreeDimensionalActivity mActivity;
+ private Bitmap mBitmap;
+ private Type mType = Type.NONE;
+ private int mX;
+ private int mY;
+ private float mIntensity = 0.5f;
+ private boolean mIsPreview = true;
+
+ private int mScale;
+
+ private Controller mController;
+
+ private Thread mThread;
+ private Boolean mCancelled;
+
+ public Effect(ThreeDimensionalActivity activity) {
+ mActivity = activity;
+ }
+
+ public void setBitmap(Bitmap bitmap, int scale) {
+ mBitmap = bitmap;
+ scaleBitmap(scale);
+ }
+
+ public static int scale(int width, int height) {
+ int scale = 1;
+ while (width / scale > PREVIEW_DIMENSION_MAX || height / scale > PREVIEW_DIMENSION_MAX) {
+ scale *= 2;
+ }
+ return scale > 1 ? scale : 1;
+ }
+
+ private void scaleBitmap(int scale) {
+ if (scale != 1) {
+ mScale = scale;
+ } else if (mBitmap != null) {
+ int width = mBitmap.getWidth(), height = mBitmap.getHeight();
+ mX = width / 2;
+ mY = height / 2;
+ mScale = scale(width, height);
+ if (mScale != 1) {
+ mBitmap = Bitmap.createScaledBitmap(mBitmap,
+ width / mScale, height / mScale, false);
+ }
+ }
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_IMAGE, mBitmap);
+ }
+
+ public void set(Type type) {
+ if (type == Type.THREE_DIMENSIONAL) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ DualCameraNativeEngine.DepthMap3D map = DualCameraNativeEngine.getInstance()
+ .getDepthMap3D(mBitmap);
+ if (map != null) {
+ Log.d(TAG, "got 3d map");
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_IMAGE, mBitmap);
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_3D_DEPTH_MAP, map);
+ } else {
+ Log.e(TAG, "cannot get 3d map");
+ }
+ }
+ }).start();
+ if (mController == null) {
+ mController = mActivity.getController();
+ }
+ mController.start();
+ } else {
+ if (mController != null) {
+ mController.stop(true);
+ }
+ mActivity.sendMessage(ThreeDimensionalActivity.MSG_UPDATE_3D_DEPTH_MAP, null);
+ request();
+ }
+ mType = type;
+ }
+
+ private void setCoordination(float x, float y) {
+ if (x >= 0 && y >= 0 && x < mBitmap.getWidth() && y < mBitmap.getHeight()) {
+ mX = (int) (x * mScale);
+ mY = (int) (y * mScale);
+ }
+ }
+
+ public void setIntensity(float intensity) {
+ if (intensity < 0) intensity = 0;
+ if (intensity > INTENSITY_MAX) intensity = 1;
+ if (intensity != mIntensity) {
+ mIntensity = intensity / INTENSITY_MAX;
+ request();
+ }
+ }
+
+ private synchronized void request() {
+ notify();
+ }
+
+
+ public void recycle() {
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ }
+ }
+
+ @Override
+ public void onMove(float deltaX, float deltaY) {
+ if (mType == Type.THREE_DIMENSIONAL && mController != null) {
+ mController.onMove(deltaX, deltaY);
+ }
+ }
+
+ @Override
+ public void onClick(float x, float y) {
+ if (mType != Type.THREE_DIMENSIONAL) {
+ setCoordination(x, y);
+ request();
+ }
+ }
+
+ @Override
+ public void onLayout(int width, int height) {
+ }
+
+ public void resume() {
+ if (mController != null && mType == Type.THREE_DIMENSIONAL) {
+ mController.start();
+ }
+ mCancelled = false;
+ mThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (!mCancelled) {
+ synchronized (Effect.this) {
+ try {
+ Effect.this.wait();
+ } catch (InterruptedException ignored) {
+ }
+ }
+ }
+ }
+ });
+ mThread.start();
+ }
+
+ public void pause() {
+ if (mController != null) {
+ mController.stop(false);
+ }
+ if (mThread != null) {
+ mCancelled = true;
+ synchronized (this) {
+ notify();
+ }
+ try {
+ mThread.join();
+ } catch (InterruptedException ignored) {
+ }
+ mThread = null;
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/GLView.java b/src/com/android/gallery3d/app/dualcam3d/GLView.java
new file mode 100755
index 000000000..3bde8937b
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/GLView.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+public class GLView extends GLSurfaceView {
+ private static final String TAG = "GLView";
+ private final com.android.gallery3d.app.dualcam3d.gl.Renderer mRenderer;
+
+ private Bitmap mBitmap;
+ private DualCameraNativeEngine.DepthMap3D mDepthMap;
+ private int mRotation;
+
+ public GLView(Context context) {
+ this(context, null);
+ }
+
+ public GLView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setEGLContextClientVersion(2);
+ mRenderer = new com.android.gallery3d.app.dualcam3d.gl.Renderer();
+ setRenderer(mRenderer);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ mRenderer.setImageBitmap(mBitmap);
+ mRenderer.set3DEffectDepthMap(mDepthMap);
+ requestRender();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mRenderer.setImageBitmap(null);
+ mRenderer.set3DEffectDepthMap(null);
+ }
+
+ public void setImageBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ mRenderer.setImageBitmap(bitmap);
+ mRenderer.set3DEffectDepthMap(null);
+ requestRender();
+ }
+
+ public void set3DEffectDepthMap(DualCameraNativeEngine.DepthMap3D map) {
+ mDepthMap = map;
+ mRenderer.set3DEffectDepthMap(map);
+ requestRender();
+ }
+
+ public void setOffset(float x, float y) {
+ mRenderer.setOffset(x, y);
+ requestRender();
+ }
+
+ public void setOffsetWithRotation(float x, float y) {
+ if (mRotation == Surface.ROTATION_0 || mRotation == Surface.ROTATION_180) {
+ //noinspection SuspiciousNameCombination
+ setOffset(y, x);
+ } else {
+ setOffset(x, y);
+ }
+ }
+
+ public void setOffsetDelta(float deltaX, float deltaY) {
+ mRenderer.setOffsetDelta(deltaX, deltaY);
+ requestRender();
+ }
+
+ public void recycle() {
+ mListener = null;
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ mBitmap = null;
+ }
+ }
+
+ public void setRotation(int rotation) {
+ mRotation = rotation;
+ }
+
+ private static final float MOVE_THRESHOLD = 1.0f;
+ private PointF mLastPoint;
+ private int mLastAction = MotionEvent.ACTION_DOWN;
+ private Listener mListener;
+
+ public interface Listener {
+ void onMove(float deltaX, float deltaY);
+
+ void onClick(float x, float y);
+
+ void onLayout(int width, int height);
+ }
+
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ Matrix invertMatrix = mRenderer.getImageInvertMatrix();
+ if (invertMatrix == null) {
+ return true;
+ }
+
+ float[] point = new float[]{event.getX(), event.getY()};
+ invertMatrix.mapPoints(point);
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mLastPoint = new PointF(point[0], point[1]);
+ mLastAction = MotionEvent.ACTION_DOWN;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mLastPoint != null) {
+ float deltaX = point[0] - mLastPoint.x,
+ deltaY = point[1] - mLastPoint.y;
+ if (mLastAction == MotionEvent.ACTION_MOVE || (Math.abs(deltaX) > MOVE_THRESHOLD
+ && Math.abs(deltaY) > MOVE_THRESHOLD)) {
+ if (mListener != null) {
+ mListener.onMove(deltaX, deltaY);
+ }
+ mLastPoint.set(point[0], point[1]);
+ mLastAction = MotionEvent.ACTION_MOVE;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mLastAction != MotionEvent.ACTION_MOVE && mListener != null) {
+ mListener.onClick(point[0], point[1]);
+ }
+ mLastPoint = null;
+ mLastAction = MotionEvent.ACTION_UP;
+ break;
+ }
+ return true;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed && mListener != null) {
+ mListener.onLayout(right - left, bottom - top);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java b/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java
new file mode 100755
index 000000000..c1212fac6
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.Window;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.app.dualcam3d.mpo.Task;
+import com.android.gallery3d.app.dualcam3d.threed.Controller;
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+import org.codeaurora.gallery.R;
+
+public class ThreeDimensionalActivity extends Activity {
+ private static final String TAG = "DualCamDemo";
+
+ final static int MSG_UPDATE_IMAGE = 1;
+ final static int MSG_UPDATE_3D_DEPTH_MAP = 2;
+ private final static int MSG_IMAGE_LOADED = 3;
+ private final static int MSG_FINISH = 4;
+
+ private Effect mEffect;
+ private GLView mImageView;
+ private Task mTask;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_IMAGE:
+ if (mImageView != null) {
+ mImageView.setImageBitmap((Bitmap) msg.obj);
+ }
+ break;
+ case MSG_UPDATE_3D_DEPTH_MAP:
+ if (mImageView != null) {
+ mImageView.set3DEffectDepthMap((DualCameraNativeEngine.DepthMap3D) msg.obj);
+ }
+ break;
+ case MSG_IMAGE_LOADED:
+ mEffect.setBitmap((Bitmap) msg.obj, msg.arg1);
+ break;
+ case MSG_FINISH:
+ mEffect.set(Effect.Type.THREE_DIMENSIONAL);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.d(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.activity_three_dimensional);
+
+ mEffect = new Effect(this);
+ processIntent();
+ init();
+ }
+
+ private void init() {
+ mImageView = (GLView) findViewById(R.id.image);
+ mImageView.setListener(mEffect);
+ mImageView.setRotation(getWindowManager().getDefaultDisplay().getRotation());
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mImageView.onResume();
+ if (mEffect != null) {
+ mEffect.resume();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mImageView.onPause();
+ if (mEffect != null) {
+ mEffect.pause();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (DualCameraNativeEngine.getInstance().isLibLoaded()) {
+ DualCameraNativeEngine.getInstance().releaseDepthMap();
+ }
+ if (mEffect != null) {
+ mEffect.recycle();
+ mEffect = null;
+ }
+ mImageView.recycle();
+ mTask.cancel();
+ super.onDestroy();
+ }
+
+ private void processIntent() {
+ Intent intent = getIntent();
+ Uri uri = intent.getData();
+ if (uri == null) {
+ finish();
+ return;
+ }
+ startLoadImage(uri);
+ }
+
+ private void startLoadImage(Uri uri) {
+ if (DualCameraNativeEngine.getInstance().isLibLoaded()) {
+ mTask = new Task(this, uri, new Task.Listener() {
+ @Override
+ public void onBitmapLoaded(Bitmap bitmap, int scale) {
+ if (bitmap != null) {
+ mHandler.obtainMessage(MSG_IMAGE_LOADED, scale, 0, bitmap).sendToTarget();
+ } else {
+ finish();
+ }
+ }
+
+ @Override
+ public int onScale(int width, int height) {
+ return Effect.scale(width, height);
+ }
+
+ @Override
+ public void onFinish(boolean result) {
+ if (!result) {
+ finish();
+ } else {
+ sendMessage(MSG_FINISH, null);
+ }
+ }
+ });
+ mTask.start(Effect.DEFAULT_BRIGHTNESS_INTENSITY);
+ }
+ }
+
+ public void sendMessage(int what, Object obj) {
+ mHandler.obtainMessage(what, obj).sendToTarget();
+ }
+
+ public Controller getController() {
+ return new Controller(mImageView, (LinearLayout) findViewById(R.id.mode_3d));
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Error.java b/src/com/android/gallery3d/app/dualcam3d/gl/Error.java
new file mode 100755
index 000000000..55f04dd32
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Error.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+import android.util.Log;
+
+class Error {
+ private static final String TAG = "GL";
+
+ public static void check() {
+ int error = GLES20.glGetError();
+ if (error != 0) {
+ Throwable t = new Throwable();
+ Log.e(TAG, "error: " + error, t);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java b/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java
new file mode 100755
index 000000000..2b9f5bac5
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+class Mesh {
+ private static final String TAG = "Mesh";
+
+ private static final float TAN_HALF_FOV =
+ (float) Math.tan(Math.toRadians(Settings.FIELD_OF_VIEW / 2));
+
+ public FloatBuffer vertices;
+ public FloatBuffer colors;
+ public FloatBuffer textures;
+ private IntBuffer indices;
+
+ private int indexLength;
+
+ public void render(Shader shader) {
+ if (vertices == null || textures == null || indices == null || indices.capacity() == 0)
+ return;
+ shader.setMesh(this);
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexLength, GLES20.GL_UNSIGNED_INT, indices);
+ }
+
+ private void rewindBuffers() {
+ vertices.position(0);
+ colors.position(0);
+ textures.position(0);
+ indices.position(0);
+ }
+
+ private static ByteBuffer allocateBuffer(int capacity) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
+ buffer.order(ByteOrder.nativeOrder());
+ return buffer;
+ }
+
+ public static Mesh create() {
+ Mesh m = new Mesh();
+
+ final int resolutionH = Settings.MESH_RESOLUTION_H;
+ final int resolutionV = Settings.MESH_RESOLUTION_V;
+ final int vertexCount = (resolutionH + 1) * (resolutionV + 1);
+ final int indexCount = resolutionH * resolutionV * 2;
+
+ m.vertices = allocateBuffer(vertexCount * 3 * 4).asFloatBuffer();
+ m.colors = allocateBuffer(vertexCount * 4 * 4).asFloatBuffer();
+ m.textures = allocateBuffer(vertexCount * 2 * 4).asFloatBuffer();
+ m.indices = allocateBuffer(indexCount * 3 * 4).asIntBuffer();
+ m.indexLength = indexCount * 3;
+
+ m.rewindBuffers();
+ return m;
+ }
+
+ private static float getVertexScale(float depth) {
+ return ((depth + Settings.CAMERA_POSITION) * TAN_HALF_FOV);
+ }
+
+ public void update(DualCameraNativeEngine.DepthMap3D depthMap, int width, int height,
+ float depth) {
+ final int resolutionH = depthMap == null ? 1 : Settings.MESH_RESOLUTION_H;
+ final int resolutionV = depthMap == null ? 1 : Settings.MESH_RESOLUTION_V;
+ indexLength = resolutionH * resolutionV * 2 * 3;
+
+ // / Correct aspect ratio of the rendered image, fit width
+ float scale = getVertexScale(Math.abs(depth));
+ if (depthMap != null) scale *= Settings.ENLARGE_IMAGE;
+ float sizeV = scale * height / width;
+
+ rewindBuffers();
+
+ for (int v = 0; v <= resolutionV; ++v) {
+ float vV = v / (float) resolutionV;
+ float v2 = sizeV - 2 * sizeV * vV;
+ int y = (int) (vV * (height - 1));
+ for (int h = 0; h <= resolutionH; ++h) {
+ float vH = h / (float) resolutionH;
+
+ int depthValue = 0;
+ if (depthMap != null) {
+ int x = (int) (vH * (width - 1));
+ depthValue = depthMap.pixels[y * depthMap.width + x];
+ }
+ vertices.put(-scale + 2 * scale * vH);
+ vertices.put(v2);
+ vertices.put(depthValue * Settings.DEPTH_RATIO);
+
+ colors.put(1f);
+ colors.put(1f);
+ colors.put(1f);
+ colors.put(1f);
+
+ textures.put(vH);
+ textures.put(vV);
+ }
+ }
+
+ for (int v = 0; v < resolutionV; ++v) {
+ for (int h = 0; h < resolutionH; ++h) {
+ int index = v * (resolutionH + 1) + h;
+
+ indices.put(index);
+ indices.put(index + (resolutionH + 1));
+ indices.put(index + 1);
+
+ indices.put(index + (resolutionH + 1));
+ indices.put(index + 1 + (resolutionH + 1));
+ indices.put(index + 1);
+ }
+ }
+ rewindBuffers();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java b/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java
new file mode 100755
index 000000000..ca8d5495d
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.graphics.RectF;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.Matrix;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+public class Renderer implements GLSurfaceView.Renderer {
+ private static final String TAG = "Renderer";
+ public static final float THETA_MAX = (float) Math.toRadians(6);
+ private final float[] mProjectionMatrix = new float[16];
+
+ private float mOffsetX;
+ private float mOffsetY;
+
+ private Bitmap mImageBitmap;
+ private DualCameraNativeEngine.DepthMap3D mDepthMap;
+
+ private boolean mImageChanged;
+ private boolean mDepthMapChanged;
+
+ private RectF mSurfaceRect;
+ private android.graphics.Matrix mImageInvertMatrix;
+
+ private final Mesh mMesh = Mesh.create();
+ private Shader mShader;
+ private final Texture mImageTexture = new Texture();
+
+ public Renderer() {
+ }
+
+ public void setImageBitmap(Bitmap bitmap) {
+ mImageBitmap = bitmap;
+ mImageChanged = true;
+ mDepthMap = null;
+ mDepthMapChanged = true;
+ setImageInvertMatrix();
+ }
+
+ public void set3DEffectDepthMap(DualCameraNativeEngine.DepthMap3D map) {
+ mDepthMap = map;
+ mDepthMapChanged = true;
+ if (map == null) {
+ mOffsetX = 0;
+ mOffsetY = 0;
+ }
+ }
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ mShader = new Shader();
+ mShader.bind();
+ GLES20.glEnable(GLES20.GL_DEPTH_TEST);
+ GLES20.glEnable(GLES20.GL_BLEND);
+ GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ Log.d(TAG, "w=" + width + "x" + height);
+ float ratio = (float) width / height;
+ float sinY = (float) Math.sin(Math.toRadians(Settings.FIELD_OF_VIEW / 2)) / ratio;
+ float cosY = (float) Math.cos(Math.toRadians(Settings.FIELD_OF_VIEW / 2));
+ float fovY = (float) Math.toDegrees(Math.atan2(sinY, cosY) * 2.f);
+ Matrix.perspectiveM(mProjectionMatrix, 0, fovY, ratio, 0.1f, 500.f);
+ GLES20.glViewport(0, 0, width, height);
+ mSurfaceRect = new RectF(0, 0, width, height);
+ setImageInvertMatrix();
+ }
+
+ private void updateImage() {
+ if (mImageChanged) {
+ mImageTexture.upload(mImageBitmap);
+ mImageTexture.bind();
+ mImageChanged = false;
+ }
+ if (mDepthMapChanged) {
+ int width = mDepthMap == null ? mImageBitmap.getWidth() : mDepthMap.width;
+ int height = mDepthMap == null ? mImageBitmap.getHeight() : mDepthMap.height;
+ mMesh.update(mDepthMap, width, height, Settings.FOREGROUND_POSITION);
+ mDepthMapChanged = false;
+ }
+ }
+
+ private void updateMatrix() {
+ float x = (float) (Math.sin(mOffsetX) * Math.cos(mOffsetY)) * Settings.CAMERA_POSITION;
+ float y = (float) (Math.sin(mOffsetY)) * Settings.CAMERA_POSITION;
+ float z = (float) (Math.cos(mOffsetX) * Math.cos(mOffsetY)) * Settings.CAMERA_POSITION;
+
+ float[] viewMatrix = new float[16];
+ Matrix.setLookAtM(viewMatrix, 0, x, y, z, 0f, 0f, Settings.FOREGROUND_POSITION,
+ 0f, 1f, 0f);
+ float[] matrix = new float[16];
+ Matrix.multiplyMM(matrix, 0, mProjectionMatrix, 0, viewMatrix, 0);
+ mShader.setMatrix(matrix);
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ if (mImageBitmap == null) {
+ return;
+ }
+
+ updateImage();
+ updateMatrix();
+
+ GLES20.glClearColor(0, 0, 0, 0);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
+ mMesh.render(mShader);
+ }
+
+ public void setOffset(float x, float y) {
+ mOffsetX = limit(x);
+ mOffsetY = limit(y);
+ }
+
+ public void setOffsetDelta(float deltaX, float deltaY) {
+ mOffsetX = limit(mOffsetX + deltaX);
+ mOffsetY = limit(mOffsetY + deltaY);
+ }
+
+ private float limit(float theta) {
+ if (theta < -THETA_MAX) return -THETA_MAX;
+ if (theta > THETA_MAX) return THETA_MAX;
+ return theta;
+ }
+
+ public android.graphics.Matrix getImageInvertMatrix() {
+ return mImageInvertMatrix;
+ }
+
+ private void setImageInvertMatrix() {
+ if (mImageBitmap != null && mSurfaceRect != null) {
+ RectF rect = new RectF(0, 0, mImageBitmap.getWidth(), mImageBitmap.getHeight());
+ if (mImageInvertMatrix == null) {
+ mImageInvertMatrix = new android.graphics.Matrix();
+ }
+ android.graphics.Matrix matrix = new android.graphics.Matrix();
+ matrix.setRectToRect(rect, mSurfaceRect, android.graphics.Matrix.ScaleToFit.CENTER);
+ matrix.invert(mImageInvertMatrix);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java b/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java
new file mode 100755
index 000000000..5321fdfc5
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.gl;
+
+class Settings {
+ // Number of horizontal subdivisions (horizontal resolution)
+ static final int MESH_RESOLUTION_H = 300;
+ // Number of vertical subdivisions (vertical resolution)
+ static final int MESH_RESOLUTION_V = 450;
+ // Field of view of the viewport (horizontal)
+ static final float FIELD_OF_VIEW = 60.0f;
+ // Distance of the viewer from the texture
+ static final float CAMERA_POSITION = 2.75f;
+ // Offset between the background and the foreground
+ static final float FOREGROUND_POSITION = 0.0f;
+
+ static final float ENLARGE_IMAGE = 1.0f;
+
+ // Some hard-coded scalar for now
+ static final float DEPTH_RATIO = 0.003f;
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java b/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java
new file mode 100755
index 000000000..3641b2676
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+
+class Shader {
+ private static final String vertexShaderCode = //
+ "uniform mat4 uMVPMatrix;" //
+ + "attribute vec4 vPosition;" //
+ + "attribute vec2 vTexCoord;" //
+ + "attribute vec4 vColor;" //
+ + "varying vec2 texCoord;" //
+ + "varying vec4 color;" //
+ + "void main() {" //
+ + " gl_Position = uMVPMatrix * vPosition;" //
+ + " texCoord = vTexCoord;" //
+ + " color = vColor;" //
+ + "}";
+
+ private static final String fragmentShaderCode = //
+ "precision mediump float;" //
+ + "uniform vec4 vColor;" //
+ + "varying vec2 texCoord;" //
+ + "varying vec4 color;" //
+ + "uniform sampler2D texSampler2D;" //
+ + "void main() {" //
+ + " gl_FragColor = texture2D(texSampler2D, texCoord);" //
+ + " gl_FragColor.w = color.w;" //
+ + "}";
+
+ private int shaderId = -1;
+
+ public Shader() {
+ int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
+ int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
+
+ shaderId = GLES20.glCreateProgram();
+ Error.check();
+ GLES20.glAttachShader(shaderId, vertexShader);
+ Error.check();
+ GLES20.glAttachShader(shaderId, fragmentShader);
+ Error.check();
+ GLES20.glLinkProgram(shaderId);
+ Error.check();
+ }
+
+ private static int loadShader(int type, String shaderCode) {
+ int shader = GLES20.glCreateShader(type);
+ GLES20.glShaderSource(shader, shaderCode);
+ Error.check();
+ GLES20.glCompileShader(shader);
+ Error.check();
+ return shader;
+ }
+
+ public void bind() {
+ GLES20.glUseProgram(shaderId);
+ }
+
+ public void setMesh(Mesh m) {
+ int vertexHandle = GLES20.glGetAttribLocation(shaderId, "vPosition");
+ GLES20.glEnableVertexAttribArray(vertexHandle);
+ GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT, false, 12, m.vertices);
+
+ int textureHandle = GLES20.glGetAttribLocation(shaderId, "vTexCoord");
+ GLES20.glEnableVertexAttribArray(textureHandle);
+ GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 8, m.textures);
+
+ int colorHandle = GLES20.glGetAttribLocation(shaderId, "vColor");
+ GLES20.glEnableVertexAttribArray(colorHandle);
+ GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, true, 16, m.colors);
+ }
+
+ public void setMatrix(float[] matrix) {
+ int matrixHandle = GLES20.glGetUniformLocation(shaderId, "uMVPMatrix");
+ GLES20.glUniformMatrix4fv(matrixHandle, 1, false, matrix, 0);
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java b/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java
new file mode 100755
index 000000000..e93df8c43
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+
+class Texture {
+ private final int[] mId = new int[1];
+ private boolean mInitialized = false;
+
+ private void init() {
+ if (!mInitialized) {
+ GLES20.glGenTextures(1, mId, 0);
+ Error.check();
+ mInitialized = true;
+ }
+ }
+
+ public void upload(Bitmap bitmap) {
+ init();
+
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mId[0]);
+ Error.check();
+
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
+ GLES20.GL_NEAREST);
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
+ GLES20.GL_LINEAR);
+
+ GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
+ }
+
+ public void bind() {
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mId[0]);
+ Error.check();
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/mpo/Task.java b/src/com/android/gallery3d/app/dualcam3d/mpo/Task.java
new file mode 100755
index 000000000..74f77465d
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/mpo/Task.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.mpo;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Point;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.tools.DualCameraNativeEngine;
+import com.android.gallery3d.mpo.MpoParser;
+
+
+import java.io.OutputStream;
+
+public class Task {
+ private static final String TAG = "ParseMpoTask";
+
+ public interface Listener {
+ void onBitmapLoaded(Bitmap bitmap, int scale);
+
+ int onScale(int width, int height);
+
+ void onFinish(boolean result);
+ }
+
+ private final Context mContext;
+ private final Uri mUri;
+ private final Listener mListener;
+ private boolean mCancelled;
+
+ private Thread mThread1;
+ private Thread mThread2;
+
+ public Task(final Context context, final Uri uri, final Listener listener) {
+ mContext = context;
+ mUri = uri;
+ mListener = listener;
+ mCancelled = false;
+ }
+
+ public void start(final float brIntensity) {
+ mThread1 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ boolean result = parse(brIntensity);
+ mListener.onFinish(result);
+ }
+ });
+ mThread1.start();
+ }
+
+ public void cancel() {
+ mCancelled = true;
+ try {
+ if (mThread1 != null) {
+ mThread1.join();
+ }
+ if (mThread2 != null) {
+ mThread2.join();
+ }
+ } catch (InterruptedException ignored) {
+ }
+ }
+
+ private boolean parse(final float brIntensity) {
+ final Bitmap[] bitmaps = new Bitmap[2];
+ final byte[][] data = new byte[2][];
+
+ MpoParser parser = MpoParser.parse(mContext, mUri);
+ if (mCancelled) return false;
+ final boolean primaryForDisplay = parser.isPrimaryForDisplay();
+ if (!primaryForDisplay) {
+ decodeDisplayImg(parser);
+ try {
+ mThread2.join();
+ mThread2 = null;
+ } catch (InterruptedException ignored) {
+ }
+ }
+
+ final Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ bitmaps[0] = BitmapFactory.decodeByteArray(data[0], 0, data[0].length);
+ data[0] = null;
+ if (!mCancelled && primaryForDisplay && brIntensity == 0) {
+ mListener.onBitmapLoaded(bitmaps[0], 1);
+ }
+ }
+ };
+ data[0] = parser.readImgData(true);
+ if (mCancelled || data[0] == null) return false;
+ if (primaryForDisplay) {
+ mThread2 = new Thread(runnable);
+ mThread2.start();
+ } else {
+ runnable.run();
+ }
+
+ data[1] = parser.readImgData(false);
+ if (mCancelled || data[1] == null) return false;
+ bitmaps[1] = BitmapFactory.decodeByteArray(data[1], 0, data[1].length);
+ data[1] = null;
+ if (bitmaps[1] == null) return false;
+
+ if (primaryForDisplay) {
+ try {
+ mThread2.join();
+ mThread2 = null;
+ } catch (InterruptedException ignored) {
+ }
+ }
+ return loadDepthMap(bitmaps, brIntensity, primaryForDisplay);
+ }
+
+ private void decodeDisplayImg(final MpoParser parser) {
+ mThread2 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inJustDecodeBounds = true;
+ byte[] data = parser.readImgData(0);
+ if (data == null && !mCancelled) {
+ mListener.onBitmapLoaded(null, 1);
+ return;
+ }
+ if (mCancelled) return;
+ BitmapFactory.decodeByteArray(data, 0, data.length, o);
+ o.inSampleSize = mListener.onScale(o.outWidth, o.outHeight);
+ o.inJustDecodeBounds = false;
+ if (mCancelled) return;
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, o);
+ if (mCancelled) return;
+ mListener.onBitmapLoaded(bitmap, o.inSampleSize);
+ }
+ });
+ mThread2.start();
+ }
+
+ public static String getLocalPathFromUri(Context context, Uri uri) {
+ Cursor cursor = context.getContentResolver().query(uri,
+ new String[]{MediaStore.Images.Media.DATA}, null, null, null);
+ if (cursor == null) {
+ return null;
+ }
+ int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ String s = cursor.moveToFirst() ? cursor.getString(index) : null;
+ cursor.close();
+ return s;
+ }
+
+ private boolean loadDepthMap(Bitmap[] bitmaps, float brIntensity, boolean primaryForDisplay) {
+ // check for pre-generated dm file
+ String mpoFilepath = getLocalPathFromUri(mContext, mUri);
+ DualCameraNativeEngine engine = DualCameraNativeEngine.getInstance();
+
+ if (mCancelled) return false;
+ boolean ok = engine.initDepthMap(bitmaps[0], bitmaps[1], mpoFilepath,
+ engine.getCalibFilepath(mContext), brIntensity);
+ bitmaps[1].recycle();
+ if (!ok) return false;
+
+ Point size = new Point();
+ ok = engine.getDepthMapSize(size);
+ if (ok) {
+ Log.d(TAG, "ddm size: " + size.x + "x" + size.y);
+ if (size.x == 0 || size.y == 0) {
+ Log.w(TAG, "invalid ddm size: " + size.x + "x" + size.y);
+ } else {
+ Bitmap depthMap = Bitmap.createBitmap(size.x, size.y, Bitmap.Config.ALPHA_8);
+ if (engine.getDepthMap(depthMap)) {
+ if (!mCancelled && brIntensity != 0 && primaryForDisplay) {
+ scaleBitmap(bitmaps[0]);
+ }
+ return true;
+ } else {
+ Log.w(TAG, "getDepthMap returned false");
+ }
+ }
+ } else {
+ Log.w(TAG, "getDepthMapSize returned false");
+ }
+ return false;
+ }
+
+ private void save(Bitmap bitmap, String name) {
+ try {
+ OutputStream os = mContext.openFileOutput(name, Context.MODE_PRIVATE);
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 95, os);
+ os.close();
+ } catch (Exception ignored) {
+ }
+ }
+
+ private void scaleBitmap(Bitmap bitmap) {
+ int width = bitmap.getWidth(), height = bitmap.getHeight();
+ int scale = mListener.onScale(width, height);
+ width /= scale;
+ height /= scale;
+
+ Bitmap b = Bitmap.createScaledBitmap(bitmap, width, height, false);
+ int[] roi = new int[4];
+ boolean result = DualCameraNativeEngine.getInstance().getPrimaryImg(0, 0, roi, true, b);
+ if (result && roi[2] != width && roi[3] != height) {
+ b = Bitmap.createBitmap(b, roi[0], roi[1], roi[2], roi[3]);
+ }
+ mListener.onBitmapLoaded(b, scale);
+ }
+} \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java b/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java
new file mode 100755
index 000000000..72f6b1141
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.threed;
+
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.app.dualcam3d.GLView;
+import com.android.gallery3d.app.dualcam3d.gl.Renderer;
+
+import org.codeaurora.gallery.R;
+
+
+public class Controller implements Gyro.Listener {
+ private static final String TAG = "Controller";
+ private static final float ANGLE_PER_PIXEL = (float) Math.toRadians(0.03f);
+
+ private final GLView mGLView;
+ private final LinearLayout mModeView;
+ private Auto mAuto;
+ private Gyro mGyro;
+
+ public Controller(GLView glView, LinearLayout modeView) {
+ mGLView = glView;
+ mModeView = modeView;
+ View.OnClickListener listener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ switch (id) {
+ case R.id.mode_gyro:
+ startGyro();
+ break;
+ case R.id.mode_auto:
+ startAuto();
+ break;
+ case R.id.mode_touch:
+ stop(false);
+ break;
+ }
+ }
+ };
+ for (int i = modeView.getChildCount() - 1; i >= 0; --i) {
+ Button b = (Button) modeView.getChildAt(i);
+ b.setOnClickListener(listener);
+ }
+ }
+
+ private boolean startGyro() {
+ stop(false);
+ if (mGyro == null) {
+ mGyro = new Gyro(mGLView.getContext());
+ if (mGyro.start()) {
+ mGyro.setListener(this);
+ return true;
+ } else {
+ mGyro = null;
+ mModeView.findViewById(R.id.mode_gyro).setEnabled(false);
+ }
+ }
+ return false;
+ }
+
+ private void startAuto() {
+ stop(false);
+ if (mAuto == null) {
+ mAuto = new Auto();
+ mAuto.start(mGLView);
+ }
+ }
+
+ public void start() {
+ if (!startGyro()) {
+ startAuto();
+ }
+// mModeView.setVisibility(View.VISIBLE);
+ }
+
+ public void stop(boolean hide) {
+ if (mGyro != null) {
+ mGyro.stop();
+ mGyro = null;
+ }
+ if (mAuto != null) {
+ mAuto.stop();
+ mAuto = null;
+ }
+// if (hide) {
+// mModeView.setVisibility(View.INVISIBLE);
+// }
+ }
+
+ @Override
+ public void onGyroChanged(float thetaX, float thetaY) {
+ mGLView.setOffsetWithRotation(thetaX, thetaY);
+ }
+
+ public void onMove(float deltaX, float deltaY) {
+ stop(false);
+ mGLView.setOffsetDelta(deltaX * ANGLE_PER_PIXEL, deltaY * ANGLE_PER_PIXEL);
+ }
+
+ private static class Auto {
+ private Thread mThread;
+ private boolean mStop;
+
+ public void start(final GLView glView) {
+ mStop = false;
+ mThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ float x = 0, y = 0, speed = 0.003f, angle = 0.87f;
+ double deltaX = angle * speed;
+ double deltaY = Math.sqrt(speed * speed - deltaX * deltaX);
+
+ while (!mStop) {
+ x += deltaX;
+ y += deltaY;
+ glView.setOffset(x, y);
+
+ if (x >= Renderer.THETA_MAX || x <= -Renderer.THETA_MAX) {
+ deltaX = -deltaX;
+ }
+ if (y >= Renderer.THETA_MAX || y <= -Renderer.THETA_MAX) {
+ deltaY = -deltaY;
+ }
+ try {
+ Thread.sleep(15);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+ });
+ mThread.start();
+ }
+
+ public void stop() {
+ mStop = true;
+ if (mThread != null) {
+ try {
+ mThread.join();
+ mThread = null;
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java b/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java
new file mode 100755
index 000000000..bb1d1c1de
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, 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.app.dualcam3d.threed;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+class Gyro implements SensorEventListener {
+ private final SensorManager mSensorManager;
+ private final Sensor mGyro;
+
+ private static final float ALPHA = 0.4f;
+ private static final float ALPHA_ORIGIN = 0.95f;
+
+ private long mPrevTimestamp;
+ private float mPrevThetaX;
+ private float mPrevThetaY;
+ private float mPrevOriginX;
+ private float mPrevOriginY;
+ private float mPrevOmegaX;
+ private float mPrevOmegaY;
+
+ private Listener mListener;
+
+ interface Listener {
+ void onGyroChanged(float thetaX, float thetaY);
+ }
+
+ Gyro(Context context) {
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ mGyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+ }
+
+ public boolean start() {
+ return mGyro != null
+ && mSensorManager.registerListener(this, mGyro, SensorManager.SENSOR_DELAY_UI);
+ }
+
+ public void stop() {
+ mSensorManager.unregisterListener(this);
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
+ float omegaX = event.values[0];
+ float omegaY = event.values[1];
+ update(omegaX, omegaY, event.timestamp);
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ private void update(float omegaX, float omegaY, long timestamp) {
+ if (mPrevTimestamp == 0) {
+ mPrevTimestamp = timestamp;
+ return;
+ }
+ float deltaTimestamp = (float) (timestamp - mPrevTimestamp) / 1000_000_000;
+
+ float thetaX = mPrevThetaX + 0.5f * (mPrevOmegaX + omegaX) * deltaTimestamp;
+ float thetaY = mPrevThetaY + 0.5f * (mPrevOmegaY + omegaY) * deltaTimestamp;
+ float smoothThetaX = ALPHA * mPrevThetaX + ((1.0f - ALPHA) * thetaX);
+ float smoothThetaY = ALPHA * mPrevThetaY + ((1.0f - ALPHA) * thetaY);
+
+ mPrevOriginX = ALPHA_ORIGIN * mPrevOriginX + (1 - ALPHA_ORIGIN) * smoothThetaX;
+ mPrevOriginY = ALPHA_ORIGIN * mPrevOriginY + (1 - ALPHA_ORIGIN) * smoothThetaY;
+
+ mPrevTimestamp = timestamp;
+ mPrevOmegaX = omegaX;
+ mPrevOmegaY = omegaY;
+ mPrevThetaX = smoothThetaX;
+ mPrevThetaY = smoothThetaY;
+
+ if (mListener != null) {
+ mListener.onGyroChanged(smoothThetaX - mPrevOriginX, smoothThetaY - mPrevOriginY);
+ }
+ }
+
+ void setListener(Listener listener) {
+ mListener = listener;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 8ada5af9b..f769b5ecd 100755
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -39,6 +39,7 @@ 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.drawable.ColorDrawable;
@@ -105,6 +106,9 @@ import com.android.gallery3d.filtershow.editors.HazeBusterEditor;
import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import com.android.gallery3d.filtershow.editors.SeeStraightEditor;
import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamSketchRepresentation;
import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
@@ -1156,6 +1160,23 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
return;
}
}
+ if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ float[] mTmpPoint = new float[2];
+ mTmpPoint[0] = dm.widthPixels/2;
+ mTmpPoint[1] = dm.heightPixels/2;
+ Matrix m = MasterImage.getImage().getScreenToImageMatrix(true);
+ m.mapPoints(mTmpPoint);
+ if (representation instanceof FilterDualCamBasicRepresentation) {
+ ((FilterDualCamBasicRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+ }
+ if (representation instanceof FilterDualCamFusionRepresentation) {
+ ((FilterDualCamFusionRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+ }
+ if (representation instanceof FilterDualCamSketchRepresentation) {
+ ((FilterDualCamSketchRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+ }
+ }
useFilterRepresentation(representation);
loadEditorPanel(representation);
@@ -1290,23 +1311,20 @@ DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
mAuxImgData == null) {
// parse failed
MasterImage.getImage().setDepthMapLoadingStatus(DdmStatus.DDM_FAILED);
- Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
- if (currentPanel instanceof MainPanel) {
- MainPanel mainPanel = (MainPanel) currentPanel;
- mainPanel.updateDualCameraButton();
- }
} else {
+ MasterImage.getImage().setDepthMapLoadingStatus(DdmStatus.DDM_LOADING);
mLoadMpoTask = new LoadMpoDataTask();
mLoadMpoTask.execute(mPrimaryImgData, mAuxImgData);
}
+ Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ if (currentPanel instanceof MainPanel) {
+ MainPanel mainPanel = (MainPanel) currentPanel;
+ mainPanel.updateDualCameraButton();
+ }
}
}
private class LoadMpoDataTask extends AsyncTask<byte[], Void, Boolean> {
- @Override
- protected void onPreExecute() {
- MasterImage.getImage().setDepthMapLoadingStatus(DdmStatus.DDM_LOADING);
- }
@Override
protected Boolean doInBackground(byte[]... params) {
diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java
index 24912bb24..055d7a430 100755
--- a/src/com/android/gallery3d/filtershow/category/MainPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/MainPanel.java
@@ -247,7 +247,23 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
dualCamButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- showPanel(DUALCAM);
+ Context context = getActivity();
+ boolean skipIntro = GalleryUtils.getBooleanPref(context,
+ context.getString(R.string.pref_dualcam_intro_show_key), false);
+ if (skipIntro) {
+ showPanel(DUALCAM);
+ } else {
+ DoNotShowAgainDialog dialog = new DoNotShowAgainDialog(
+ R.string.dual_camera_effects, R.string.dual_camera_effects_intro,
+ R.string.pref_dualcam_intro_show_key) {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+ showPanel(DUALCAM);
+ }
+ };
+ dialog.show(getFragmentManager(), "dualcam_intro");
+ }
}
});
@@ -263,10 +279,10 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
} else if(!skipIntro) {
DoNotShowAgainDialog dialog = new DoNotShowAgainDialog(
R.string.trueportrait, R.string.trueportrait_intro,
- R.string.pref_trueportrait_intro_show_key) {
+ R.string.pref_trueportrait_intro_show_key);
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
- super.onDismiss(dialog);
if(facesDetected) {
showPanel(TRUEPORTRAIT);
} else {
@@ -274,7 +290,7 @@ public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelega
TruePortraitNativeEngine.getInstance().showNoFaceDetectedDialog(getFragmentManager());
}
}
- };
+ });
dialog.show(getFragmentManager(), "trueportrait_intro");
} else {
v.setEnabled(false);
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
index 2371ccb15..f4490b330 100644..100755
--- a/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -30,37 +30,58 @@
package com.android.gallery3d.filtershow.editors;
import android.content.Context;
+import android.content.DialogInterface;
import android.net.Uri;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.Button;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-import org.codeaurora.gallery.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;
+import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
+import com.android.gallery3d.util.GalleryUtils;
+
+import org.codeaurora.gallery.R;
-public class EditorDualCamFusion extends ImageOnlyEditor {
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class EditorDualCamFusion extends Editor {
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);
- }
- };
+ private Uri mUnderlayUri = Uri.EMPTY;
public EditorDualCamFusion() {
super(ID);
}
+ @Override
+ public boolean showsActionBar() {
+ return true;
+ }
+
+ @Override
+ public boolean showsActionBarControls() {
+ return false;
+ }
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ menu.clear();
+ }
+
public boolean useUtilityPanel() {
return true;
}
@@ -77,48 +98,123 @@ public class EditorDualCamFusion extends ImageOnlyEditor {
@Override
public void setEditPanelUI(View editControl) {
- editControl.setVisibility(View.GONE);
+ ViewGroup controlContainer = (ViewGroup) editControl;
+ controlContainer.removeAllViews();
+
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+ (Context.LAYOUT_INFLATER_SERVICE);
+ View controls = inflater.inflate(R.layout.filtershow_seekbar, controlContainer);
+ View seekbar = controls.findViewById(R.id.primarySeekBar);
+ seekbar.setVisibility(View.GONE);
+ View saveButton = controls.findViewById(R.id.slider_save);
+ if (saveButton != null) {
+ saveButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ FilterShowActivity activity = (FilterShowActivity) mContext;
+ finalApplyCalled();
+ activity.leaveSeekBarPanel();
+ }
+ });
+ }
+ View cancelButton = controls.findViewById(R.id.slider_cancel);
+ if (cancelButton != null) {
+ cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ FilterShowActivity activity = (FilterShowActivity) mContext;
+ activity.cancelCurrentFilter();
+ activity.leaveSeekBarPanel();
+ }
+ });
+ }
}
@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();
+ accessoryViewList.removeAllViews();
+
+ LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+ (Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.filtershow_actionbar_dualcam_fusion, accessoryViewList);
+
+ View pickUnderlayBtn = accessoryViewList.findViewById(R.id.pick_underlay);
+ pickUnderlayBtn.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+ }
+ });
+
+ // Look for previous underlay
+ String fusionUnderlay = GalleryUtils.getStringPref(mContext,
+ mContext.getString(R.string.pref_dualcam_fusion_underlay_key), null);
+ Uri fusionUri = Uri.EMPTY;
+
+ if (fusionUnderlay != null) {
+ fusionUri = Uri.parse(fusionUnderlay);
+ if (!uriExists(mContext, fusionUri))
+ fusionUri = Uri.EMPTY;
}
- }
- 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);
- }
+ setUnderlayImageUri(fusionUri);
}
-
- protected void updateText() {
- if(mPickUnderlayBtn != null) {
- updateEffectButton(hasSegment());
+ @Override
+ public void resume() {
+ if (mUnderlayUri.equals(Uri.EMPTY)) {
+ // No underlay set.
+ boolean skipIntro = GalleryUtils.getBooleanPref(mContext,
+ mContext.getString(R.string.pref_dualcam_fusion_intro_show_key), false);
+ if (!skipIntro) {
+ FragmentManager fm = ((FilterShowActivity) mContext).getSupportFragmentManager();
+ DoNotShowAgainDialog dialog =
+ (DoNotShowAgainDialog) fm.findFragmentByTag("dualcam_fusion_intro");
+ if (dialog == null) {
+ dialog = new DoNotShowAgainDialog(
+ R.string.fusion_pick_background, R.string.dualcam_fusion_intro,
+ R.string.pref_dualcam_fusion_intro_show_key) {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ FilterShowActivity activity = (FilterShowActivity) mContext;
+ activity.cancelCurrentFilter();
+ activity.leaveSeekBarPanel();
+ }
+ };
+ dialog.setOnOkButtonClickListener(new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+ }
+ });
+ dialog.setCancelable(true);
+ dialog.show(fm, "dualcam_fusion_intro");
+ } else if (dialog.isDetached()) {
+ FragmentTransaction ft = fm.beginTransaction();
+ ft.attach(dialog);
+ ft.commit();
+ } else if (dialog.isHidden()) {
+ FragmentTransaction ft = fm.beginTransaction();
+ ft.show(dialog);
+ ft.commit();
+ }
+ }
}
}
- private boolean hasSegment() {
+ public void setUnderlayImageUri(Uri uri) {
+ mUnderlayUri = uri;
FilterRepresentation filter = getLocalRepresentation();
- if(filter instanceof FilterDualCamFusionRepresentation) {
- return !((FilterDualCamFusionRepresentation) filter).getPoint().equals(-1,-1);
+ if (filter instanceof FilterDualCamFusionRepresentation) {
+ mImageFusion.setUnderlay(uri);
+ commitLocalRepresentation();
+
+ // save fusion underlay uri
+ GalleryUtils.setStringPref(mContext,
+ mContext.getString(R.string.pref_dualcam_fusion_underlay_key),
+ (uri != null) ? uri.toString() : null);
}
- return false;
}
@Override
@@ -130,4 +226,17 @@ public class EditorDualCamFusion extends ImageOnlyEditor {
mImageFusion.setRepresentation(dualRep);
}
}
+
+ private boolean uriExists(Context context, Uri uri) {
+ try {
+ InputStream stream = context.getContentResolver().openInputStream(uri);
+ stream.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
index da6118c63..5879197b3 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
@@ -179,15 +179,15 @@ public class EditorTruePortraitFusion extends Editor {
if(dialog == null) {
dialog = new DoNotShowAgainDialog(
R.string.fusion_pick_background, R.string.trueportrait_fusion_intro,
- R.string.pref_trueportrait_fusion_intro_show_key) {
+ R.string.pref_trueportrait_fusion_intro_show_key);
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
FilterShowActivity activity = (FilterShowActivity) mContext;
activity.cancelCurrentFilter();
activity.leaveSeekBarPanel();
}
- };
+ });
dialog.setOnOkButtonClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
index b9c24fc27..0d98c7b0e 100644..100755
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -423,22 +423,30 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
public void addDualCam(Context context) {
int[] textId = {
R.string.focus,
- R.string.halo
+ R.string.halo,
+ R.string.motion,
+ R.string.posterize
};
int[] overlayId = {
R.drawable.focus,
- R.drawable.halo
+ R.drawable.halo,
+ R.drawable.motion,
+ R.drawable.posterize
};
String[] serializationNames = {
"DUAL_CAM_FOCUS",
- "DUAL_CAM_HALO"
+ "DUAL_CAM_HALO",
+ "DUAL_CAM_MOTION",
+ "DUAL_CAM_POSTERIZE"
};
// intensity range as defined by ddm lib
int[][] minMaxValues = {
{0,5,10},
+ {0,5,10},
+ {0,5,10},
{0,5,10}
};
@@ -460,13 +468,42 @@ public abstract class BaseFiltersManager implements FiltersManagerInterface {
addRepresentation(dualCam);
}
- FilterDualCamSketchRepresentation sketch = new FilterDualCamSketchRepresentation(
- context.getString(R.string.sketch), R.string.sketch);
- sketch.setOverlayId(R.drawable.sketch);
- sketch.setOverlayOnly(true);
- sketch.setSerializationName("DUAL_CAM_SKETCH");
- mDualCam.add(sketch);
- addRepresentation(sketch);
+ int[] textId2 = {
+ R.string.sketch,
+ R.string.zoom,
+ R.string.bw,
+ R.string.blackboard,
+ R.string.whiteboard,
+ R.string.dc_negative
+ };
+
+ int[] overlayId2 = {
+ R.drawable.sketch,
+ R.drawable.zoom,
+ R.drawable.bw,
+ R.drawable.blackboard,
+ R.drawable.whiteboard,
+ R.drawable.negative
+ };
+
+ String[] serializationNames2 = {
+ "DUAL_CAM_SKETCH",
+ "DUAL_CAM_ZOOM",
+ "DUAL_CAM_BW",
+ "DUAL_CAM_BLACKBOARD",
+ "DUAL_CAM_WHITEBOARD",
+ "DUAL_CAM_NEGATIVE"
+ };
+
+ for (int i = 0; i < textId2.length; i++) {
+ FilterDualCamSketchRepresentation dualCam = new FilterDualCamSketchRepresentation(
+ context.getString(textId2[i]), textId2[i]);
+ dualCam.setOverlayId(overlayId2[i]);
+ dualCam.setOverlayOnly(true);
+ dualCam.setSerializationName(serializationNames2[i]);
+ mDualCam.add(dualCam);
+ addRepresentation(dualCam);
+ }
mDualCam.add(getRepresentation(ImageFilterDualCamFusion.class));
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
index df34fedbe..7b74d3561 100755
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
@@ -159,6 +159,18 @@ public class ImageFilterDualCamFusion extends ImageFilter {
roiRectF.right = (float)(roiRect[0] + roiRect[2])/(float)filteredW;
roiRectF.bottom = (float)(roiRect[1] + roiRect[3])/(float)filteredH;
+ int zoomOrientation = MasterImage.getImage().getZoomOrientation();
+ if (zoomOrientation == ImageLoader.ORI_ROTATE_90 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_180 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_270 ||
+ zoomOrientation == ImageLoader.ORI_TRANSPOSE ||
+ zoomOrientation == ImageLoader.ORI_TRANSVERSE) {
+ Matrix mt = new Matrix();
+ mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+ 0.5f, 0.5f);
+ mt.mapRect(roiRectF);
+ }
+
// Check for ROI cropping
if(!FilterCropRepresentation.getNil().equals(roiRectF)) {
if(FilterCropRepresentation.getNil().equals(holder.crop)) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
index 97712db75..21906540b 100755
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamSketch.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -116,8 +116,33 @@ public class ImageFilterDualCamSketch extends ImageFilter {
}
filteredBitmap = MasterImage.getImage().getBitmapCache().getBitmap(filteredW, filteredH, BitmapCache.FILTERS);
- result = DualCameraNativeEngine.getInstance().applySketch(point.x, point.y,
- roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+
+ switch (mParameters.getTextId()) {
+ case R.string.sketch:
+ result = DualCameraNativeEngine.getInstance().applySketch(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.zoom:
+ result = DualCameraNativeEngine.getInstance().applyZoom(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.bw:
+ result = DualCameraNativeEngine.getInstance().applyBlackAndWhite(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.blackboard:
+ result = DualCameraNativeEngine.getInstance().applyBlackBoard(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.whiteboard:
+ result = DualCameraNativeEngine.getInstance().applyWhiteBoard(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.dc_negative:
+ result = DualCameraNativeEngine.getInstance().applyNegative(point.x, point.y,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ }
if(result == false) {
Log.e(TAG, "Imagelib API failed");
@@ -148,6 +173,18 @@ public class ImageFilterDualCamSketch extends ImageFilter {
roiRectF.right = (float)(roiRect[0] + roiRect[2])/(float)filteredW;
roiRectF.bottom = (float)(roiRect[1] + roiRect[3])/(float)filteredH;
+ int zoomOrientation = MasterImage.getImage().getZoomOrientation();
+ if (zoomOrientation == ImageLoader.ORI_ROTATE_90 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_180 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_270 ||
+ zoomOrientation == ImageLoader.ORI_TRANSPOSE ||
+ zoomOrientation == ImageLoader.ORI_TRANSVERSE) {
+ Matrix mt = new Matrix();
+ mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+ 0.5f, 0.5f);
+ mt.mapRect(roiRectF);
+ }
+
// Check for ROI cropping
if(!FilterCropRepresentation.getNil().equals(roiRectF)) {
if(FilterCropRepresentation.getNil().equals(holder.crop)) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
index 49728f84c..7bcba5162 100755
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -121,15 +121,24 @@ public class ImageFilterDualCamera extends ImageFilter {
filteredBitmap = MasterImage.getImage().getBitmapCache().getBitmap(filteredW, filteredH, BitmapCache.FILTERS);
- switch(mParameters.getTextId()) {
- case R.string.focus:
- result = DualCameraNativeEngine.getInstance().applyFocus(point.x, point.y, intensity,
- roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
- break;
- case R.string.halo:
- result = DualCameraNativeEngine.getInstance().applyHalo(point.x, point.y, intensity,
- roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
- break;
+ switch (mParameters.getTextId()) {
+ case R.string.focus:
+ result = DualCameraNativeEngine.getInstance().applyFocus(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.halo:
+ result = DualCameraNativeEngine.getInstance().applyHalo(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.motion:
+ result = DualCameraNativeEngine.getInstance().applyMotion(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+ case R.string.posterize:
+ result = DualCameraNativeEngine.getInstance().applyPosterize(point.x, point.y, intensity,
+ roiRect, quality != FilterEnvironment.QUALITY_FINAL, filteredBitmap);
+ break;
+
}
if(result == false) {
@@ -162,6 +171,18 @@ public class ImageFilterDualCamera extends ImageFilter {
roiRectF.right = (float)(roiRect[0] + roiRect[2])/(float)filteredW;
roiRectF.bottom = (float)(roiRect[1] + roiRect[3])/(float)filteredH;
+ int zoomOrientation = MasterImage.getImage().getZoomOrientation();
+ if (zoomOrientation == ImageLoader.ORI_ROTATE_90 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_180 ||
+ zoomOrientation == ImageLoader.ORI_ROTATE_270 ||
+ zoomOrientation == ImageLoader.ORI_TRANSPOSE ||
+ zoomOrientation == ImageLoader.ORI_TRANSVERSE) {
+ Matrix mt = new Matrix();
+ mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+ 0.5f, 0.5f);
+ mt.mapRect(roiRectF);
+ }
+
// Check for ROI cropping
if(!FilterCropRepresentation.getNil().equals(roiRectF)) {
if(FilterCropRepresentation.getNil().equals(holder.crop)) {
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
index 764312199..99304c5a8 100755
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
@@ -238,7 +238,7 @@ public final class GeometryMathUtils {
}
}
- private static int getRotationForOrientation(int orientation) {
+ public static int getRotationForOrientation(int orientation) {
switch (orientation) {
case ImageLoader.ORI_ROTATE_90:
return 90;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
index 962519373..cb864aa2d 100644..100755
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -75,6 +75,6 @@ public class ImageDualCamera extends ImageShow {
}
private void calcScreenMapping() {
- mToOrig = getScreenToImageMatrix(true);
+ mToOrig = MasterImage.getImage().getScreenToImageMatrix(true);
}
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index 0a13da737..09950262e 100644..100755
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -21,6 +21,7 @@ import java.util.Vector;
import android.animation.Animator;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
@@ -767,7 +768,7 @@ public class MasterImage implements RenderingRequestCaller {
return m;
}
- private Matrix getScreenToImageMatrix(boolean reflectRotation) {
+ public Matrix getScreenToImageMatrix(boolean reflectRotation) {
Matrix m = getImageToScreenMatrix(reflectRotation);
Matrix invert = new Matrix();
m.invert(invert);
@@ -960,7 +961,7 @@ public class MasterImage implements RenderingRequestCaller {
return mPreset.contains(FilterRepresentation.TYPE_TINYPLANET);
}
- public boolean loadMpo(byte[] primaryMpoData, byte[] auxiliaryMpoData) {
+ public boolean loadMpo(Context context, byte[] primaryMpoData, byte[] auxiliaryMpoData, Uri uri){
boolean loaded = false;
if(auxiliaryMpoData != null) {
@@ -971,7 +972,7 @@ public class MasterImage implements RenderingRequestCaller {
}
// check for pre-generated dm file
- String mpoFilepath = ImageLoader.getLocalPathFromUri(getActivity(), getUri());
+ String mpoFilepath = ImageLoader.getLocalPathFromUri(context, uri);
// read auxiliary image and generate depth map.
Bitmap auxiliaryBm = BitmapFactory.decodeByteArray(auxiliaryMpoData, 0, auxiliaryMpoData.length);
@@ -983,7 +984,7 @@ public class MasterImage implements RenderingRequestCaller {
DualCameraNativeEngine.getInstance().initDepthMap(
primaryBm, auxiliaryBm, mpoFilepath,
- DualCameraNativeEngine.getInstance().getCalibFilepath(mActivity));
+ DualCameraNativeEngine.getInstance().getCalibFilepath(context),1.0f);
primaryBm.recycle();
primaryBm = null;
@@ -1017,6 +1018,10 @@ public class MasterImage implements RenderingRequestCaller {
return loaded;
}
+ public boolean loadMpo(byte[] primaryMpoData, byte[] auxiliaryMpoData) {
+ return loadMpo(getActivity(), primaryMpoData, auxiliaryMpoData, getUri());
+ }
+
public void setFusionUnderlay(Bitmap underlay) {
mFusionUnderlay = underlay;
}
diff --git a/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java b/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
index f44f4d6d1..56b349677 100644..100755
--- a/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
+++ b/src/com/android/gallery3d/filtershow/tools/DualCameraNativeEngine.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -38,6 +38,9 @@ import android.util.Log;
public class DualCameraNativeEngine {
private static final String TAG = "DualCameraNativeEngine";
+
+ public static final float DEFAULT_BRIGHTNESS_INTENSITY = 1.0f;
+
static {
try {
System.loadLibrary("jni_dualcamera");
@@ -56,7 +59,7 @@ public class DualCameraNativeEngine {
DDM_LOADING,
DDM_LOADED,
DDM_FAILED
- };
+ }
public static final String DEPTH_MAP_EXT = "dm";
private static final String CALIBRATION_FILENAME = "ddm_calib_file.dat";
@@ -64,10 +67,11 @@ public class DualCameraNativeEngine {
private static DualCameraNativeEngine mInstance;
- private DualCameraNativeEngine() {}
+ private DualCameraNativeEngine() {
+ }
public static void createInstance() {
- if(mInstance == null) {
+ if (mInstance == null) {
mInstance = new DualCameraNativeEngine();
}
}
@@ -86,7 +90,7 @@ public class DualCameraNativeEngine {
return calibFile.getAbsolutePath();
}
- native public boolean initDepthMap(Bitmap primaryRGBA, Bitmap auxiliaryRGBA, String mpoFilepath, String calibFilepath);
+ native public boolean initDepthMap(Bitmap primaryRGBA, Bitmap auxiliaryRGBA, String mpoFilepath, String calibFilepath, float brIntensity);
native public void releaseDepthMap();
@@ -94,11 +98,59 @@ public class DualCameraNativeEngine {
native public boolean getDepthMap(Bitmap dataBuffer);
+ native private boolean get3DEffectImages(Bitmap bitmap, Bitmap depthMap);
+
native public boolean applyFocus(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+ native public boolean applyFocusStar(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyFocusHexagon(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
native public boolean applyHalo(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+ native public boolean applyMotion(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
native public boolean applySketch(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+ native public boolean applyZoom(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyBlackAndWhite(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyBlackBoard(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyWhiteBoard(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyPosterize(int focusPointX, int focusPointY, float intensity, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean applyNegative(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
native public boolean getForegroundImg(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ native public boolean getPrimaryImg(int focusPointX, int focusPointY, int[] roiRect, boolean isPreview, Bitmap outBm);
+
+ public static class DepthMap3D {
+ public char[] pixels;
+ public int width;
+ public int height;
+ }
+
+ public DepthMap3D getDepthMap3D(Bitmap bitmap) {
+ int width = bitmap.getWidth(), height = bitmap.getHeight();
+ Bitmap depthMap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
+ boolean ok = get3DEffectImages(bitmap, depthMap);
+ if (!ok) return null;
+
+ DepthMap3D map = new DepthMap3D();
+ map.width = width;
+ map.height = height;
+ map.pixels = new char[width * height];
+
+ int[] pixels = new int[width * height];
+ depthMap.getPixels(pixels, 0, width, 0, 0, width, height);
+ for (int i = width * height - 1; i >= 0; --i) {
+ map.pixels[i] = (char) (pixels[i] & 0xff);
+ }
+ depthMap.recycle();
+ return map;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java b/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
index e9245d540..bea6d5be0 100644
--- a/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
+++ b/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
@@ -49,6 +49,8 @@ public class DoNotShowAgainDialog extends DialogFragment {
private int mMessageId;
private CheckBox mDoNotShowAgainChk;
private DialogInterface.OnClickListener mButtonClickListener;
+ private DialogInterface.OnDismissListener mDialogDismissListener;
+ private DialogInterface.OnCancelListener mCancelListener;
public DoNotShowAgainDialog(int titleId, int msgId, int sharedPrefKeyId) {
mTitleId = titleId;
@@ -83,4 +85,27 @@ public class DoNotShowAgainDialog extends DialogFragment {
public void setOnOkButtonClickListener(DialogInterface.OnClickListener listener) {
mButtonClickListener = listener;
}
+
+ public void setOnDismissListener (DialogInterface.OnDismissListener listener) {
+ mDialogDismissListener = listener;
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ super.onDismiss(dialog);
+ if (mDialogDismissListener != null) {
+ mDialogDismissListener.onDismiss(dialog);
+ }
+ }
+
+ public void setOnCancelListener(DialogInterface.OnCancelListener listener) {
+ mCancelListener = listener;
+ }
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ if (mCancelListener != null) {
+ mCancelListener.onCancel(dialog);
+ }
+ }
}
diff --git a/src/com/android/gallery3d/mpo/MpoParser.java b/src/com/android/gallery3d/mpo/MpoParser.java
index b872db640..06ab6e54f 100644..100755
--- a/src/com/android/gallery3d/mpo/MpoParser.java
+++ b/src/com/android/gallery3d/mpo/MpoParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 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
@@ -304,6 +304,75 @@ public class MpoParser {
return depthMap;
}
+ public byte[] readImgData(int index) {
+ if (mMpEntries.isEmpty()) return null;
+ MpEntry mpEntry = mMpEntries.get(index);
+ if (mpEntry == null) return null;
+
+ InputStream is = null;
+ ByteArrayOutputStream os = null;
+ byte[] data = 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");
+ os = new ByteArrayOutputStream(data.length);
+ os.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);
+
+ os.write(read);
+ }
+
+ if (validJpg)
+ data = os.toByteArray();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ Utils.closeSilently(is);
+ Utils.closeSilently(os);
+ }
+
+ return data;
+ }
+
+ public boolean isPrimaryForDisplay() {
+ return mMpEntries.size() == 2;
+ }
+
class MpEntry {
int mImgAttribute;
int mImgSize;