summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Yoo <jyoo@codeaurora.org>2016-06-30 14:16:44 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-16 16:10:18 -0700
commit2fceef1ed0dfb3cb35062b6f6ebe8ca68e7bf87c (patch)
tree86a0cfd7ddb6ddde91dfb310d47d8f6e289f9d78
parent039e6e3a2baa4c510306d32683cf258eb8e00e10 (diff)
downloadandroid_packages_apps_Snap-2fceef1ed0dfb3cb35062b6f6ebe8ca68e7bf87c.tar.gz
android_packages_apps_Snap-2fceef1ed0dfb3cb35062b6f6ebe8ca68e7bf87c.tar.bz2
android_packages_apps_Snap-2fceef1ed0dfb3cb35062b6f6ebe8ca68e7bf87c.zip
SnapdragonCamera: Bestpicture scene filter
Adding best picture selection scene filter Change-Id: Ifa0f544e80d161eaef743d611c712d8db48e5631 CRs-Fixed: 1050663
-rw-r--r--Android.mk1
-rwxr-xr-xAndroidManifest.xml5
-rw-r--r--res/drawable-hdpi/pick_the_best_photo.pngbin0 -> 55579 bytes
-rw-r--r--res/drawable-hdpi/pick_the_best_photo_selected.pngbin0 -> 1151 bytes
-rw-r--r--res/drawable-hdpi/pick_the_best_photo_unselected.pngbin0 -> 1005 bytes
-rw-r--r--res/drawable-xhdpi/pick_the_best_photo.pngbin0 -> 56319 bytes
-rw-r--r--res/drawable-xhdpi/pick_the_best_photo_selected.pngbin0 -> 1726 bytes
-rw-r--r--res/drawable-xhdpi/pick_the_best_photo_unselected.pngbin0 -> 1523 bytes
-rw-r--r--res/drawable-xxhdpi/pick_the_best_photo.pngbin0 -> 57779 bytes
-rw-r--r--res/drawable-xxhdpi/pick_the_best_photo_selected.pngbin0 -> 2306 bytes
-rw-r--r--res/drawable-xxhdpi/pick_the_best_photo_unselected.pngbin0 -> 2118 bytes
-rw-r--r--res/layout/bestpicture_editor.xml69
-rw-r--r--res/layout/bestpicture_page.xml58
-rw-r--r--res/values/camera2arrays.xml3
-rw-r--r--res/values/qcomstrings.xml3
-rw-r--r--src/com/android/camera/BestpictureActivity.java348
-rw-r--r--src/com/android/camera/BestpictureFragment.java93
-rwxr-xr-xsrc/com/android/camera/CameraActivity.java9
-rw-r--r--src/com/android/camera/CaptureModule.java8
-rw-r--r--src/com/android/camera/SettingsManager.java3
-rw-r--r--src/com/android/camera/imageprocessor/PostProcessor.java24
-rw-r--r--src/com/android/camera/imageprocessor/filter/BestpictureFilter.java252
-rw-r--r--src/com/android/camera/imageprocessor/filter/UbifocusFilter.java21
-rw-r--r--src/com/android/camera/ui/DotsView.java98
-rw-r--r--src/com/android/camera/ui/DotsViewItem.java35
25 files changed, 1015 insertions, 15 deletions
diff --git a/Android.mk b/Android.mk
index 5077a1c06..2f9723815 100644
--- a/Android.mk
+++ b/Android.mk
@@ -5,6 +5,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES += xmp_toolkit
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 37ce25f8b..e316ee6ed 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -164,6 +164,11 @@
android:configChanges="keyboardHidden|orientation|screenSize">
</activity>
+ <activity
+ android:name="com.android.camera.BestpictureActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize">
+ </activity>
+
<receiver android:name="com.android.camera.DisableCameraReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
diff --git a/res/drawable-hdpi/pick_the_best_photo.png b/res/drawable-hdpi/pick_the_best_photo.png
new file mode 100644
index 000000000..f0b892136
--- /dev/null
+++ b/res/drawable-hdpi/pick_the_best_photo.png
Binary files differ
diff --git a/res/drawable-hdpi/pick_the_best_photo_selected.png b/res/drawable-hdpi/pick_the_best_photo_selected.png
new file mode 100644
index 000000000..d2b5f1508
--- /dev/null
+++ b/res/drawable-hdpi/pick_the_best_photo_selected.png
Binary files differ
diff --git a/res/drawable-hdpi/pick_the_best_photo_unselected.png b/res/drawable-hdpi/pick_the_best_photo_unselected.png
new file mode 100644
index 000000000..13bdec3e3
--- /dev/null
+++ b/res/drawable-hdpi/pick_the_best_photo_unselected.png
Binary files differ
diff --git a/res/drawable-xhdpi/pick_the_best_photo.png b/res/drawable-xhdpi/pick_the_best_photo.png
new file mode 100644
index 000000000..629af4a09
--- /dev/null
+++ b/res/drawable-xhdpi/pick_the_best_photo.png
Binary files differ
diff --git a/res/drawable-xhdpi/pick_the_best_photo_selected.png b/res/drawable-xhdpi/pick_the_best_photo_selected.png
new file mode 100644
index 000000000..92f11cb17
--- /dev/null
+++ b/res/drawable-xhdpi/pick_the_best_photo_selected.png
Binary files differ
diff --git a/res/drawable-xhdpi/pick_the_best_photo_unselected.png b/res/drawable-xhdpi/pick_the_best_photo_unselected.png
new file mode 100644
index 000000000..a558c7a1f
--- /dev/null
+++ b/res/drawable-xhdpi/pick_the_best_photo_unselected.png
Binary files differ
diff --git a/res/drawable-xxhdpi/pick_the_best_photo.png b/res/drawable-xxhdpi/pick_the_best_photo.png
new file mode 100644
index 000000000..2374b1848
--- /dev/null
+++ b/res/drawable-xxhdpi/pick_the_best_photo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/pick_the_best_photo_selected.png b/res/drawable-xxhdpi/pick_the_best_photo_selected.png
new file mode 100644
index 000000000..522e9f2ba
--- /dev/null
+++ b/res/drawable-xxhdpi/pick_the_best_photo_selected.png
Binary files differ
diff --git a/res/drawable-xxhdpi/pick_the_best_photo_unselected.png b/res/drawable-xxhdpi/pick_the_best_photo_unselected.png
new file mode 100644
index 000000000..98e18b07e
--- /dev/null
+++ b/res/drawable-xxhdpi/pick_the_best_photo_unselected.png
Binary files differ
diff --git a/res/layout/bestpicture_editor.xml b/res/layout/bestpicture_editor.xml
new file mode 100644
index 000000000..6c35c27a1
--- /dev/null
+++ b/res/layout/bestpicture_editor.xml
@@ -0,0 +1,69 @@
+<?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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/bestpicture_pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:background="#b2191919">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true">
+ <TextView
+ android:id="@+id/bestpicture_done"
+ android:text="@string/bestpicture_done"
+ android:textColor="#ffffff"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+ </LinearLayout>
+ </RelativeLayout>
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="bottom"
+ android:background="#b2191919">
+ <com.android.camera.ui.DotsView
+ android:id="@+id/dots_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true" />
+ </RelativeLayout>
+</FrameLayout>
diff --git a/res/layout/bestpicture_page.xml b/res/layout/bestpicture_page.xml
new file mode 100644
index 000000000..d6b6022c8
--- /dev/null
+++ b/res/layout/bestpicture_page.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <ImageView
+ android:id="@+id/image_view"
+ android:adjustViewBounds="true"
+ android:scaleType="fitXY"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/click_view">
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="150dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true">
+ <ImageView
+ android:id="@+id/picture_select"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:layout_marginRight="20dp"/>
+ </LinearLayout>
+ </RelativeLayout>
+</FrameLayout>
diff --git a/res/values/camera2arrays.xml b/res/values/camera2arrays.xml
index 37a33ec17..bb5eeca50 100644
--- a/res/values/camera2arrays.xml
+++ b/res/values/camera2arrays.xml
@@ -133,6 +133,7 @@
<item>8</item>
<item>9</item>
<item>-1</item>
+ <item>103</item>
</string-array>
<!-- Camera Preferences Scene Mode dialog box entries -->
@@ -153,6 +154,7 @@
<item>@string/pref_camera_scenemode_entry_beach</item>
<item>@string/pref_camera_scenemode_entry_snow</item>
<item>@string/pref_camera_scenemode_entry_asd</item>
+ <item>@string/pref_camera_scenemode_entry_bestpicture</item>
</string-array>
<array name="pref_camera2_scenemode_thumbnails" translatable="false">
@@ -172,6 +174,7 @@
<item>@drawable/ic_scene_mode_beach</item>
<item>@drawable/ic_scene_mode_snow</item>
<item>@drawable/ic_scene_mode_smartauto</item>
+ <item>@drawable/pick_the_best_photo</item>
</array>
<string-array name="pref_camera2_whitebalance_entryvalues" translatable="false">
diff --git a/res/values/qcomstrings.xml b/res/values/qcomstrings.xml
index f8f1f1963..c75be9ab0 100644
--- a/res/values/qcomstrings.xml
+++ b/res/values/qcomstrings.xml
@@ -1023,5 +1023,8 @@
<string name="pref_camera2_videosnap_entry_enable" translatable="true">Enable</string>
<string name="pref_camera2_videosnap_entry_disable" translatable="true">Disable</string>
<string name="pref_camera2_trackingfocus_title" translatable="true">Tracking Focus</string>
+ <string name="pref_camera_scenemode_entry_bestpicture" translatable="true">BestPicture</string>
+ <string name="bestpicture_done" translatable="true">DONE</string>
+ <string name="bestpicture_at_least_one_picture" translatable="true">At least, one picture has to be chosen.</string>
</resources>
diff --git a/src/com/android/camera/BestpictureActivity.java b/src/com/android/camera/BestpictureActivity.java
new file mode 100644
index 000000000..bb519e74f
--- /dev/null
+++ b/src/com/android/camera/BestpictureActivity.java
@@ -0,0 +1,348 @@
+/*
+ * 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.camera;
+
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.v13.app.FragmentStatePagerAdapter;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+import android.view.Display;
+import android.view.Menu;
+import android.view.View;
+import android.support.v4.app.FragmentActivity;
+import android.widget.Toast;
+
+import com.android.camera.exif.ExifInterface;
+import com.android.camera.ui.DotsView;
+import com.android.camera.ui.DotsViewItem;
+import com.android.camera.ui.RotateTextToast;
+import com.android.camera.util.CameraUtil;
+
+import org.codeaurora.snapcam.R;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+public class BestpictureActivity extends FragmentActivity{
+ private static final String TAG = "BestpictureActivity";
+ public static final String[] NAMES = {
+ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09"
+ };
+
+ public static final int NUM_IMAGES = 10;
+
+ private ViewPager mImagePager;
+ private PagerAdapter mImagePagerAdapter;
+ private int mWidth;
+ private int mHeight;
+ private String mFilesPath;
+ private ProgressDialog mProgressDialog;
+ private BestpictureActivity mActivity;
+ private DotsView mDotsView;
+ private ImageItems mImageItems;
+ private ImageLoadingThread mLoadingThread;
+ private PhotoModule.NamedImages mNamedImages;
+ private Uri mPlaceHolderUri;
+ public static int BESTPICTURE_ACTIVITY_CODE = 11;
+
+ static class ImageItems implements Parcelable, DotsViewItem {
+ private Bitmap[] mBitmap;
+ private boolean[] mChosen;
+ private BestpictureActivity mActivity;
+
+ public ImageItems(BestpictureActivity activity) {
+ mBitmap = new Bitmap[NUM_IMAGES];
+ mChosen = new boolean[NUM_IMAGES];
+ for (int i = 0; i < mChosen.length; i++) {
+ if (i == 0) {
+ mChosen[i] = true;
+ } else {
+ mChosen[i] = false;
+ }
+ }
+ mActivity = activity;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public Bitmap getBitmap(int index) {
+ return mBitmap[index];
+ }
+
+ public void setBitmap(int index, Bitmap bitmap) {
+ mBitmap[index] = bitmap;
+ }
+
+ @Override
+ public int getTotalItemNums() {
+ return NUM_IMAGES;
+ }
+
+ public boolean isChosen(int index) {
+ return mChosen[index];
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+
+ public void toggleImageSelection(int num) {
+ mChosen[num] = !mChosen[num];
+ boolean isChosen = false;
+ for(int i=0; i < mChosen.length; i++) {
+ isChosen |= mChosen[i];
+ }
+ if(!isChosen) {
+ mChosen[num] = true;
+ RotateTextToast.makeText(mActivity,
+ mActivity.getResources().getString(R.string.bestpicture_at_least_one_picture),
+ Toast.LENGTH_SHORT).show();
+ }
+ mActivity.mDotsView.update();
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle state) {
+ super.onCreate(state);
+ mActivity = this;
+ mFilesPath = getFilesDir()+"/Bestpicture";
+ setContentView(R.layout.bestpicture_editor);
+ Display display = getWindowManager().getDefaultDisplay();
+ Point size = new Point();
+ display.getSize(size);
+ mWidth = size.x/2;
+ mHeight = size.y/2;
+ mNamedImages = new PhotoModule.NamedImages();
+
+ mImageItems = new ImageItems(mActivity);
+ mDotsView = (DotsView) findViewById(R.id.dots_view);
+ mDotsView.setItems(mImageItems);
+ mPlaceHolderUri = getIntent().getData();
+
+ mImagePager = (ViewPager) findViewById(R.id.bestpicture_pager);
+ mImagePagerAdapter = new ImagePagerAdapter(getFragmentManager());
+ mImagePager.setAdapter(mImagePagerAdapter);
+ mImagePager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ mDotsView.update(position, positionOffset);
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ }
+ });
+ findViewById(R.id.bestpicture_done).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ int index = -1;
+ for(int i=0; i < mImageItems.mChosen.length; i++) {
+ if (mImageItems.mChosen[i]) {
+ if(index != -1) {
+ new SaveImageTask().execute(mFilesPath + "/" + NAMES[i] + ".jpg");
+ } else {
+ index = i;
+ saveForground(mFilesPath + "/" + NAMES[i] + ".jpg");
+ }
+ }
+ }
+ setResult(RESULT_OK, new Intent());
+ finish();
+ }
+ });
+ }
+
+ private class ImageLoadingThread extends Thread {
+ public void run() {
+ showProgressDialog();
+ for(int i=0; i < NUM_IMAGES; i++) {
+ String path = mFilesPath + "/" + BestpictureActivity.NAMES[i] + ".jpg";
+ final BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(path, o);
+ ExifInterface exif = new ExifInterface();
+ int orientation = 0;
+ try {
+ exif.readExif(path);
+ orientation = Exif.getOrientation(exif);
+ } catch (IOException e) {
+ }
+ int h = o.outHeight;
+ int w = o.outWidth;
+ int sample = 1;
+ if (h > mHeight || w > mWidth) {
+ while (h / sample / 2 > mHeight && w / sample / 2 > mWidth) {
+ sample *= 2;
+ }
+ }
+
+ o.inJustDecodeBounds = false;
+ o.inSampleSize = sample;
+ Bitmap bitmap = BitmapFactory.decodeFile(path, o);
+ if (orientation != 0) {
+ Matrix matrix = new Matrix();
+ matrix.setRotate(orientation);
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), matrix, false);
+ }
+ mImageItems.setBitmap(i, bitmap);
+ }
+ dismissProgressDialog();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mLoadingThread == null) {
+ mLoadingThread = new ImageLoadingThread();
+ mLoadingThread.start();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ }
+
+ private void showProgressDialog() {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mProgressDialog = ProgressDialog.show(mActivity, "", "Processing...", true, false);
+ mProgressDialog.show();
+ }
+ });
+ }
+
+ private void dismissProgressDialog() {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ return true;
+ }
+
+ private class ImagePagerAdapter extends FragmentStatePagerAdapter {
+ public ImagePagerAdapter(android.app.FragmentManager manager) {
+ super(manager);
+ }
+
+ @Override
+ public android.app.Fragment getItem(int imageNum) {
+ while(mImageItems.getBitmap(imageNum) == null) {
+ try {
+ Thread.sleep(5);
+ } catch (Exception e) {
+ }
+ }
+ return BestpictureFragment.create(imageNum, mImageItems);
+ }
+
+ @Override
+ public int getCount() {
+ return NUM_IMAGES;
+ }
+ }
+
+ private void saveForground(String path) {
+ long captureStartTime = System.currentTimeMillis();
+ mNamedImages.nameNewImage(captureStartTime);
+ PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ String outPath = mPlaceHolderUri.getPath();
+ try {
+ FileOutputStream out = new FileOutputStream(outPath);
+ FileInputStream in = new FileInputStream(path);
+ byte[] buf = new byte[4096];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ in.close();
+ out.close();
+ } catch (Exception e) {
+ }
+ }
+
+ private class SaveImageTask extends AsyncTask<String, Void, Void> {
+ protected Void doInBackground(String... path) {
+ long captureStartTime = System.currentTimeMillis();
+ mNamedImages.nameNewImage(captureStartTime);
+ PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ String outPath = Storage.generateFilepath(title, "jpeg");
+ try {
+ FileOutputStream out = new FileOutputStream(outPath);
+ FileInputStream in = new FileInputStream(path[0]);
+ byte[] buf = new byte[4096];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ in.close();
+ out.close();
+ } catch (Exception e) {
+ }
+ Uri uri = Uri.fromFile(new File(outPath));
+ Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
+ sendBroadcast(intent);
+ return null;
+ }
+
+ protected void onPostExecute(Void v) {
+ }
+ }
+}
diff --git a/src/com/android/camera/BestpictureFragment.java b/src/com/android/camera/BestpictureFragment.java
new file mode 100644
index 000000000..6dc4ebd59
--- /dev/null
+++ b/src/com/android/camera/BestpictureFragment.java
@@ -0,0 +1,93 @@
+/*
+ * 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.camera;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import org.codeaurora.snapcam.R;
+
+public class BestpictureFragment extends Fragment {
+ public static final String PARAM_IMAGE_NUM = "image_num";
+ private static final String TAG = "BestpictureFilter";
+ private int mImageNum;
+ private ImageView mImageView;
+ private ImageView mPictureSelectButton;
+ private BestpictureActivity.ImageItems mImageItems;
+
+ public static BestpictureFragment create(int imageNum, BestpictureActivity.ImageItems items) {
+ BestpictureFragment fragment = new BestpictureFragment();
+ Bundle args = new Bundle();
+ args.putInt(PARAM_IMAGE_NUM, imageNum);
+ args.putParcelable("imageItems", items);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ public BestpictureFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mImageNum = getArguments().getInt(PARAM_IMAGE_NUM);
+ mImageItems = getArguments().getParcelable("imageItems");
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ ViewGroup rootView = (ViewGroup) inflater
+ .inflate(R.layout.bestpicture_page, container, false);
+ mImageView = (ImageView) rootView.findViewById(R.id.image_view);
+ mPictureSelectButton = (ImageView) rootView.findViewById(R.id.picture_select);
+ initSelectButton();
+ mImageView.setImageBitmap(mImageItems.getBitmap(mImageNum));
+ rootView.findViewById(R.id.picture_select).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ mImageItems.toggleImageSelection(mImageNum);
+ initSelectButton();
+ }
+ });
+ return rootView;
+ }
+
+ private void initSelectButton() {
+ if(mImageItems.isChosen(mImageNum)) {
+ mPictureSelectButton.setBackground(getResources().getDrawable(R.drawable.pick_the_best_photo_selected, null));
+ } else {
+ mPictureSelectButton.setBackground(getResources().getDrawable(R.drawable.pick_the_best_photo_unselected, null));
+ }
+ }
+} \ No newline at end of file
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 5666331fa..a330f6a5f 100755
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -16,6 +16,8 @@
package com.android.camera;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.view.Display;
import android.graphics.Point;
import android.Manifest;
@@ -1642,6 +1644,13 @@ public class CameraActivity extends Activity
if(resultCode == RESULT_OK) {
mCaptureModule.setRefocusLastTaken(false);
}
+ } else if (requestCode == BestpictureActivity.BESTPICTURE_ACTIVITY_CODE) {
+ if(resultCode == RESULT_OK) {
+ byte[] jpeg = data.getByteArrayExtra("thumbnail");
+ if(jpeg != null) {
+ updateThumbnail(jpeg);
+ }
+ }
} else {
super.onActivityResult(requestCode, resultCode, data);
}
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index cace45ba7..899f40f7d 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -158,8 +158,6 @@ public class CaptureModule implements CameraModule, PhotoController,
// we can change it based on memory status or other requirements.
private static final int LONGSHOT_CANCEL_THRESHOLD = 40 * 1024 * 1024;
- private static final int MAX_IMAGE_NUM = 8;
-
MeteringRectangle[][] mAFRegions = new MeteringRectangle[MAX_NUM_CAM][];
MeteringRectangle[][] mAERegions = new MeteringRectangle[MAX_NUM_CAM][];
CaptureRequest.Key<Byte> BayerMonoLinkEnableKey =
@@ -1266,7 +1264,7 @@ public class CaptureModule implements CameraModule, PhotoController,
} else {
// No Clearsight
mImageReader[i] = ImageReader.newInstance(mPictureSize.getWidth(),
- mPictureSize.getHeight(), imageFormat, MAX_IMAGE_NUM);
+ mPictureSize.getHeight(), imageFormat, PostProcessor.MAX_REQUIRED_IMAGE_NUM);
if((mPostProcessor.isFilterOn() || getFrameFilters().size() != 0)
&& i == getMainCameraId()) {
mImageReader[i].setOnImageAvailableListener(mPostProcessor, mImageAvailableHandler);
@@ -1316,7 +1314,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mVideoSnapshotImageReader.close();
}
mVideoSnapshotImageReader = ImageReader.newInstance(mVideoSnapshotSize.getWidth(),
- mVideoSnapshotSize.getHeight(), ImageFormat.JPEG, MAX_IMAGE_NUM);
+ mVideoSnapshotSize.getHeight(), ImageFormat.JPEG, mPostProcessor.MAX_REQUIRED_IMAGE_NUM);
mVideoSnapshotImageReader.setOnImageAvailableListener(
new ImageReader.OnImageAvailableListener() {
@Override
@@ -1667,6 +1665,8 @@ public class CaptureModule implements CameraModule, PhotoController,
return PostProcessor.FILTER_UBIFOCUS;
} else if (mode == SettingsManager.SCENE_MODE_AUTO_INT && StillmoreFilter.isSupportedStatic()) {
return PostProcessor.FILTER_STILLMORE;
+ } else if (mode == SettingsManager.SCENE_MODE_BESTPICTURE_INT) {
+ return PostProcessor.FILTER_BESTPICTURE;
}
return PostProcessor.FILTER_NONE;
}
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
index 23c472698..ae46b9587 100644
--- a/src/com/android/camera/SettingsManager.java
+++ b/src/com/android/camera/SettingsManager.java
@@ -45,6 +45,7 @@ import android.util.Rational;
import android.util.Size;
import com.android.camera.imageprocessor.filter.BeautificationFilter;
+import com.android.camera.imageprocessor.filter.BestpictureFilter;
import com.android.camera.imageprocessor.filter.OptizoomFilter;
import com.android.camera.imageprocessor.filter.TrackingFocusFrameListener;
import com.android.camera.imageprocessor.filter.UbifocusFilter;
@@ -77,6 +78,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
public static final int SCENE_MODE_DUAL_INT = 100;
public static final int SCENE_MODE_OPTIZOOM_INT = 101;
public static final int SCENE_MODE_UBIFOCUS_INT = 102;
+ public static final int SCENE_MODE_BESTPICTURE_INT = 103;
public static final String SCENE_MODE_DUAL_STRING = "100";
public static final String KEY_CAMERA_SAVEPATH = "pref_camera2_savepath_key";
public static final String KEY_RECORD_LOCATION = "pref_camera2_recordlocation_key";
@@ -846,6 +848,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
if (mIsMonoCameraPresent) modes.add(SCENE_MODE_DUAL_STRING); // need special case handle for dual mode
if (OptizoomFilter.isSupportedStatic()) modes.add(SCENE_MODE_OPTIZOOM_INT + "");
if (UbifocusFilter.isSupportedStatic() && cameraId == CaptureModule.BAYER_ID) modes.add(SCENE_MODE_UBIFOCUS_INT + "");
+ if (BestpictureFilter.isSupportedStatic() && cameraId == CaptureModule.BAYER_ID) modes.add(SCENE_MODE_BESTPICTURE_INT + "");
for (int mode : sceneModes) {
modes.add("" + mode);
}
diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java
index 1fa908945..295707afd 100644
--- a/src/com/android/camera/imageprocessor/PostProcessor.java
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -51,6 +51,7 @@ import com.android.camera.MediaSaveService;
import com.android.camera.PhotoModule;
import com.android.camera.SettingsManager;
import com.android.camera.exif.ExifInterface;
+import com.android.camera.imageprocessor.filter.BestpictureFilter;
import com.android.camera.imageprocessor.filter.OptizoomFilter;
import com.android.camera.imageprocessor.filter.SharpshooterFilter;
import com.android.camera.imageprocessor.filter.StillmoreFilter;
@@ -78,8 +79,11 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
public static final int FILTER_SHARPSHOOTER = 2;
public static final int FILTER_UBIFOCUS = 3;
public static final int FILTER_STILLMORE = 4;
- public static final int FILTER_MAX = 5;
+ public static final int FILTER_BESTPICTURE = 5;
+ public static final int FILTER_MAX = 6;
+ //Max image is now Bestpicture filter with 10
+ public static final int MAX_REQUIRED_IMAGE_NUM = 10;
private int mCurrentNumImage = 0;
private ImageFilter mFilter;
private int mFilterIndex;
@@ -290,6 +294,9 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
case FILTER_STILLMORE:
mFilter = new StillmoreFilter(mController);
break;
+ case FILTER_BESTPICTURE:
+ mFilter = new BestpictureFilter(mController, mActivity);
+ break;
}
}
@@ -440,10 +447,12 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
}
}
}
- //Start processing FrameProcessor filter as well
- for (ImageFilter filter : mController.getFrameFilters()) {
- filter.init(resultImage.width, resultImage.height, resultImage.stride, resultImage.stride);
- filter.addImage(resultImage.outBuffer, null, 0, new Boolean(false));
+ if(resultImage != null) {
+ //Start processing FrameProcessor filter as well
+ for (ImageFilter filter : mController.getFrameFilters()) {
+ filter.init(resultImage.width, resultImage.height, resultImage.stride, resultImage.stride);
+ filter.addImage(resultImage.outBuffer, null, 0, new Boolean(false));
+ }
}
//End processing FrameProessor filter
clear();
@@ -451,10 +460,11 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
if(mWatchdog != null) {
mWatchdog.stopMonitor();
}
- if((resultImage.outRoi.left + resultImage.outRoi.width() > resultImage.width) ||
+ if(resultImage == null ||
+ (resultImage.outRoi.left + resultImage.outRoi.width() > resultImage.width) ||
(resultImage.outRoi.top + resultImage.outRoi.height() > resultImage.height)
) {
- Log.e(TAG, "Processed outRoi is not within picture range");
+ Log.d(TAG, "Result image is not valid.");
} else {
if(mFilter != null && DEBUG_FILTER) {
bytes = nv21ToJpeg(mDebugResultImage, mOrientation);
diff --git a/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java b/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java
new file mode 100644
index 000000000..638d037ce
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java
@@ -0,0 +1,252 @@
+/*
+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.camera.imageprocessor.filter;
+
+import android.content.Intent;
+import android.graphics.ImageFormat;
+import android.graphics.Rect;
+import android.graphics.YuvImage;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.camera.BestpictureActivity;
+import com.android.camera.CameraActivity;
+import com.android.camera.CaptureModule;
+import com.android.camera.MediaSaveService;
+import com.android.camera.PhotoModule;
+import com.android.camera.imageprocessor.PostProcessor;
+import com.android.camera.util.CameraUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BestpictureFilter implements ImageFilter {
+ public static final int NUM_REQUIRED_IMAGE = 10;
+ private int mWidth;
+ private int mHeight;
+ private int mStrideY;
+ private int mStrideVU;
+ private static String TAG = "BestpictureFilter";
+ private static final boolean DEBUG = false;
+ private static boolean mIsSupported = true;
+ private CaptureModule mModule;
+ private CameraActivity mActivity;
+ private int mOrientation = 0;
+ final String[] NAMES = {"00.jpg", "01.jpg", "02.jpg", "03.jpg",
+ "04.jpg", "05.jpg", "06.jpg", "07.jpg", "08.jpg"
+ ,"09.jpg"};
+
+ private final static int TIME_DELAY = 50;
+ private int mSavedCount = 0;
+ private PhotoModule.NamedImages mNamedImages;
+ private ByteBuffer mBY;
+ private ByteBuffer mBVU;
+
+ private static void Log(String msg) {
+ if (DEBUG) {
+ Log.d(TAG, msg);
+ }
+ }
+
+ public BestpictureFilter(CaptureModule module, CameraActivity activity) {
+ mModule = module;
+ mActivity = activity;
+ mNamedImages = new PhotoModule.NamedImages();
+ }
+
+ @Override
+ public List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder) {
+ List<CaptureRequest> list = new ArrayList<CaptureRequest>();
+ for(int i=0; i < NUM_REQUIRED_IMAGE; i++) {
+ list.add(builder.build());
+ }
+ return list;
+ }
+
+ @Override
+ public String getStringName() {
+ return "BestpictureFilter";
+ }
+
+ @Override
+ public int getNumRequiredImage() {
+ return NUM_REQUIRED_IMAGE;
+ }
+
+ @Override
+ public void init(int width, int height, int strideY, int strideVU) {
+ Log("init");
+ mWidth = width/2*2;
+ mHeight = height/2*2;
+ mStrideY = strideY/2*2;
+ mStrideVU = strideVU / 2 * 2;
+ Log("width: " + mWidth + " height: " + mHeight + " strideY: " + mStrideY + " strideVU: " + mStrideVU);
+ }
+
+ @Override
+ public void deinit() {
+ Log("deinit");
+ }
+
+ @Override
+ public void addImage(final ByteBuffer bY, final ByteBuffer bVU, final int imageNum, Object param) {
+ Log("addImage");
+ if(imageNum == 0) {
+ mOrientation = CameraUtil.getJpegRotation(mModule.getMainCameraId(), mModule.getDisplayOrientation());
+ mSavedCount = 0;
+ mBY = bY;
+ mBVU = bVU;
+ }
+ new Thread() {
+ public void run() {
+ saveToPrivateFile(imageNum, nv21ToJpeg(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation));
+ mSavedCount++;
+ }
+ }.start();
+ }
+
+ @Override
+ public ResultImage processImage() {
+ long captureStartTime = System.currentTimeMillis();
+ mNamedImages.nameNewImage(captureStartTime);
+ PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ long date = (name == null) ? -1 : name.date;
+ mActivity.getMediaSaveService().addImage(
+ nv21ToJpeg(mBY, mBVU, new Rect(0, 0, mWidth, mHeight), mOrientation), title, date, null, mWidth, mHeight,
+ mOrientation, null, new MediaSaveService.OnMediaSavedListener() {
+ @Override
+ public void onMediaSaved(Uri uri) {
+ if (uri != null) {
+ mActivity.notifyNewMedia(uri);
+ }
+ startBestpictureActivity(uri);
+ }
+ }
+ , mActivity.getContentResolver(), "jpeg");
+ while(mSavedCount < NUM_REQUIRED_IMAGE) {
+ try {
+ Thread.sleep(1);
+ } catch (Exception e) {
+ }
+ }
+ return null;
+ }
+
+ private void startBestpictureActivity(Uri uri) {
+ Intent intent = new Intent();
+ intent.setData(uri);
+ intent.setClass(mActivity, BestpictureActivity.class);
+ mActivity.startActivityForResult(intent, BestpictureActivity.BESTPICTURE_ACTIVITY_CODE);
+ }
+
+ @Override
+ public boolean isSupported() {
+ return mIsSupported;
+ }
+
+ @Override
+ public boolean isFrameListener() {
+ return false;
+ }
+
+ @Override
+ public boolean isManualMode() {
+ return false;
+ }
+
+ @Override
+ public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) throws CameraAccessException {
+ for(int i=0; i < NUM_REQUIRED_IMAGE; i++) {
+ captureSession.capture(builder.build(), callback, handler);
+ try {
+ Thread.sleep(TIME_DELAY);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ public static boolean isSupportedStatic() {
+ return mIsSupported;
+ }
+
+ private byte[] nv21ToJpeg(ByteBuffer bY, ByteBuffer bVU, Rect roi, int orientation) {
+ ByteBuffer buf = ByteBuffer.allocate(mStrideY*mHeight*3/2);
+ buf.put(bY);
+ bY.rewind();
+ if(bVU != null) {
+ buf.put(bVU);
+ bVU.rewind();
+ }
+ BitmapOutputStream bos = new BitmapOutputStream(1024);
+ YuvImage im = new YuvImage(buf.array(), ImageFormat.NV21,
+ mWidth, mHeight, new int[]{mStrideY, mStrideVU});
+ im.compressToJpeg(roi, 50, bos);
+ byte[] bytes = bos.getArray();
+ bytes = PostProcessor.addExifTags(bytes, orientation);
+ return bytes;
+ }
+
+ private class BitmapOutputStream extends ByteArrayOutputStream {
+ public BitmapOutputStream(int size) {
+ super(size);
+ }
+
+ public byte[] getArray() {
+ return buf;
+ }
+ }
+
+ private void saveToPrivateFile(final int index, final byte[] bytes) {
+ String filesPath = mActivity.getFilesDir()+"/Bestpicture";
+ File file = new File(filesPath);
+ if(!file.exists()) {
+ file.mkdir();
+ }
+ file = new File(filesPath+"/"+NAMES[index]);
+ try {
+ FileOutputStream out = new FileOutputStream(file);
+ out.write(bytes, 0, bytes.length);
+ out.close();
+ } catch (Exception e) {
+ }
+ }
+}
diff --git a/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java b/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
index b410e01b4..c68b5091e 100644
--- a/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
@@ -63,7 +63,7 @@ public class UbifocusFilter implements ImageFilter {
private int mStrideY;
private int mStrideVU;
private static String TAG = "UbifocusFilter";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final int FOCUS_ADJUST_TIME_OUT = 200;
private static final int META_BYTES_SIZE = 25;
private int temp;
@@ -76,6 +76,8 @@ public class UbifocusFilter implements ImageFilter {
final String[] NAMES = {"00.jpg", "01.jpg", "02.jpg", "03.jpg",
"04.jpg", "DepthMapImage.y", "AllFocusImage.jpg"};
+ private int mSavedCount = 0;
+
private static void Log(String msg) {
if (DEBUG) {
Log.d(TAG, msg);
@@ -122,18 +124,24 @@ public class UbifocusFilter implements ImageFilter {
}
@Override
- public void addImage(ByteBuffer bY, ByteBuffer bVU, int imageNum, Object param) {
+ public void addImage(final ByteBuffer bY, final ByteBuffer bVU, final int imageNum, Object param) {
Log("addImage");
if(imageNum == 0) {
mModule.setRefocusLastTaken(false);
mOrientation = CameraUtil.getJpegRotation(mModule.getMainCameraId(), mModule.getDisplayOrientation());
+ mSavedCount = 0;
}
- saveToPrivateFile(imageNum, nv21ToJpeg(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation));
int yActualSize = bY.remaining();
int vuActualSize = bVU.remaining();
if(nativeAddImage(bY, bVU, yActualSize, vuActualSize, imageNum) < 0) {
Log.e(TAG, "Fail to add image");
}
+ new Thread() {
+ public void run() {
+ saveToPrivateFile(imageNum, nv21ToJpeg(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation));
+ mSavedCount++;
+ }
+ }.start();
}
@Override
@@ -151,7 +159,12 @@ public class UbifocusFilter implements ImageFilter {
saveToPrivateFile(NAMES.length - 1, nv21ToJpeg(mOutBuf, null, new Rect(roi[0], roi[1], roi[0] + roi[2], roi[1] + roi[3]), mOrientation));
mModule.setRefocusLastTaken(true);
}
-
+ while(mSavedCount < NUM_REQUIRED_IMAGE) {
+ try {
+ Thread.sleep(1);
+ } catch (Exception e) {
+ }
+ }
ResultImage result = new ResultImage(mOutBuf, new Rect(roi[0], roi[1], roi[0]+roi[2], roi[1] + roi[3]), mWidth, mHeight, mStrideY);
Log("processImage done");
return result;
diff --git a/src/com/android/camera/ui/DotsView.java b/src/com/android/camera/ui/DotsView.java
new file mode 100644
index 000000000..f08b96713
--- /dev/null
+++ b/src/com/android/camera/ui/DotsView.java
@@ -0,0 +1,98 @@
+/*
+ * 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.camera.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class DotsView extends View {
+ private Paint mTargetPaint;
+ private int mPosition;
+ private float mPositionOffset;
+ private DotsViewItem mItems;
+
+ public DotsView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mTargetPaint = new Paint();
+ mTargetPaint.setColor(Color.WHITE);
+ mTargetPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ }
+
+ public void update(int position, float positionOffest) {
+ mPosition = position;
+ mPositionOffset = positionOffest;
+ invalidate();
+ }
+
+ public void setItems(DotsViewItem item) {
+ mItems = item;
+ }
+
+ public void update() {
+ invalidate();
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ if(mItems == null) {
+ return;
+ }
+
+ int dx = canvas.getWidth()/(mItems.getTotalItemNums()+1);
+ int dy = canvas.getHeight()/(mItems.getTotalItemNums()+1);
+ int y = canvas.getHeight()/2;
+ float radius = Math.min(dx, dy)/2f;
+ for(int i=0; i < mItems.getTotalItemNums(); i++) {
+ if(i-1 == mPosition && mPositionOffset > 0f) {
+ drawDot(canvas, (i + 1) * dx, y, radius + radius * mPositionOffset, mItems.isChosen(i));
+ } else if(i+1 == mPosition && mPositionOffset < 0f) {
+ drawDot(canvas, (i + 1) * dx, y, radius - radius*mPositionOffset, mItems.isChosen(i));
+ } else if(i == mPosition) {
+ drawDot(canvas, (i + 1) * dx, y, radius + radius * (1 - Math.abs(mPositionOffset)), mItems.isChosen(i));
+ } else {
+ drawDot(canvas, (i + 1) * dx, y, radius, mItems.isChosen(i));
+ }
+ }
+ }
+
+ private void drawDot(Canvas canvas, float cx, float cy, float radius, boolean isChosen) {
+ if(isChosen) {
+ mTargetPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ canvas.drawCircle(cx, cy, radius, mTargetPaint);
+ } else {
+ mTargetPaint.setStyle(Paint.Style.STROKE);
+ canvas.drawCircle(cx, cy, radius, mTargetPaint);
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/DotsViewItem.java b/src/com/android/camera/ui/DotsViewItem.java
new file mode 100644
index 000000000..eb342938c
--- /dev/null
+++ b/src/com/android/camera/ui/DotsViewItem.java
@@ -0,0 +1,35 @@
+/*
+ * 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.camera.ui;
+
+public interface DotsViewItem {
+ int getTotalItemNums();
+ boolean isChosen(int index);
+}