summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Yoo <jyoo@codeaurora.org>2016-06-15 16:34:57 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-07-07 09:41:00 -0700
commitc8513bf1f30d0cf0257feaf4956e5179cfefe52b (patch)
treece19b18241ff94ba26e9bba5b2f41886e8103d8c
parent12d17d80e1227e9164e7e0aa7524cd39d23bf124 (diff)
downloadandroid_packages_apps_Snap-c8513bf1f30d0cf0257feaf4956e5179cfefe52b.tar.gz
android_packages_apps_Snap-c8513bf1f30d0cf0257feaf4956e5179cfefe52b.tar.bz2
android_packages_apps_Snap-c8513bf1f30d0cf0257feaf4956e5179cfefe52b.zip
SnapdragonCamera: Adding ubifocus post proc filter
Introducing ubifocus to camera2. Change-Id: I611bea207b9cbbde56a23720b22a5a5e3daa215f CRs-Fixed: 1035245
-rw-r--r--res/values/camera2arrays.xml2
-rw-r--r--src/com/android/camera/CameraActivity.java15
-rw-r--r--src/com/android/camera/CaptureModule.java107
-rw-r--r--src/com/android/camera/CaptureUI.java16
-rw-r--r--src/com/android/camera/RefocusActivity.java56
-rw-r--r--src/com/android/camera/SettingsManager.java19
-rw-r--r--src/com/android/camera/imageprocessor/PostProcessor.java38
-rw-r--r--src/com/android/camera/imageprocessor/filter/BeautificationFilter.java17
-rw-r--r--src/com/android/camera/imageprocessor/filter/ImageFilter.java12
-rw-r--r--src/com/android/camera/imageprocessor/filter/OptizoomFilter.java12
-rw-r--r--src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java13
-rw-r--r--src/com/android/camera/imageprocessor/filter/TrackingFocusFrameListener.java17
-rw-r--r--src/com/android/camera/imageprocessor/filter/UbifocusFilter.java269
13 files changed, 533 insertions, 60 deletions
diff --git a/res/values/camera2arrays.xml b/res/values/camera2arrays.xml
index c991dbf92..25105ba65 100644
--- a/res/values/camera2arrays.xml
+++ b/res/values/camera2arrays.xml
@@ -109,7 +109,7 @@
<item>0</item>
<item>100</item>
<item>18</item>
- <item>-1</item>
+ <item>102</item>
<item>101</item>
<item>3</item>
<item>4</item>
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index e3b4573d1..68d9c7c3a 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -249,6 +249,7 @@ public class CameraActivity extends Activity
private Cursor mCursor;
private WakeLock mWakeLock;
+ private static final int REFOCUS_ACTIVITY_CODE = 1;
private class MyOrientationEventListener
extends OrientationEventListener {
@@ -576,6 +577,16 @@ public class CameraActivity extends Activity
return;
}
}
+ if (mCurrentModule instanceof CaptureModule) {
+ if (((CaptureModule) mCurrentModule).isRefocus()) {
+ Intent intent = new Intent();
+ intent.setClass(this, RefocusActivity.class);
+ intent.setData(uri);
+ intent.setFlags(RefocusActivity.MAP_ROTATED);
+ startActivityForResult(intent, REFOCUS_ACTIVITY_CODE);
+ return;
+ }
+ }
try {
Intent intent = IntentHelper.getGalleryIntent(this);
intent.setAction(Intent.ACTION_VIEW);
@@ -1624,6 +1635,10 @@ public class CameraActivity extends Activity
if (requestCode == REQ_CODE_DONT_SWITCH_TO_PREVIEW) {
mResetToPreviewOnResume = false;
mIsEditActivityInProgress = false;
+ } else if (requestCode == REFOCUS_ACTIVITY_CODE) {
+ if(resultCode == RESULT_OK) {
+ mCaptureModule.setRefocusLastTaken(false);
+ }
} else {
super.onActivityResult(requestCode, resultCode, data);
}
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 078707a7f..cc9de40c2 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -201,6 +201,7 @@ public class CaptureModule implements CameraModule, PhotoController,
private CameraCharacteristics mMainCameraCharacteristics;
private int mDisplayRotation;
private int mDisplayOrientation;
+ private boolean mIsRefocus = false;
/**
* A {@link CameraCaptureSession } for camera preview.
@@ -398,13 +399,14 @@ public class CaptureModule implements CameraModule, PhotoController,
});
mFirstPreviewLoaded = true;
}
-
- Face[] faces = result.get(CaptureResult.STATISTICS_FACES);
- mPreviewFaces = faces;
- if(faces != null && faces.length != 0) {
- mStickyFaces = faces;
+ if (id == getMainCameraId()) {
+ Face[] faces = result.get(CaptureResult.STATISTICS_FACES);
+ mPreviewFaces = faces;
+ if (faces != null && faces.length != 0) {
+ mStickyFaces = faces;
+ }
+ mPreviewCaptureResult = result;
}
- mPreviewCaptureResult = result;
updateCaptureStateMachine(id, result);
}
@@ -763,11 +765,23 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
- private void setAFModeToPreview(int id, int afMode) {
+ public void setAFModeToPreview(int id, int afMode) {
Log.d(TAG, "setAFModeToPreview " + afMode);
mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AF_MODE, afMode);
applyAFRegions(mPreviewRequestBuilder[id], id);
applyAERegions(mPreviewRequestBuilder[id], id);
+ mPreviewRequestBuilder[id].setTag(id);
+ try {
+ mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
+ .build(), mCaptureCallback, mCameraHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setFocusDistanceToPreview(int id, float fd) {
+ mPreviewRequestBuilder[id].set(CaptureRequest.LENS_FOCUS_DISTANCE, fd);
+ mPreviewRequestBuilder[id].setTag(id);
try {
mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id]
.build(), mCaptureCallback, mCameraHandler);
@@ -781,6 +795,10 @@ public class CaptureModule implements CameraModule, PhotoController,
mSettingsManager.reinit(getMainCameraId());
}
+ public boolean isRefocus() {
+ return mIsRefocus;
+ }
+
public boolean getRecordLocation() {
String value = mSettingsManager.getValue(SettingsManager.KEY_RECORD_LOCATION);
if (value == null) value = RecordLocationPreference.VALUE_NONE;
@@ -921,9 +939,32 @@ public class CaptureModule implements CameraModule, PhotoController,
mPreviewRequestBuilder[id].set(BayerMonoLinkEnableKey, (byte) 0);
}
}
-
private void captureStillPicture(final int id) {
Log.d(TAG, "captureStillPicture " + id);
+ mIsRefocus = false;
+ CameraCaptureSession.CaptureCallback captureCallback = new CameraCaptureSession.CaptureCallback() {
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ Log.d(TAG, "captureStillPicture onCaptureCompleted: " + id);
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureFailure result) {
+ Log.d(TAG, "captureStillPicture onCaptureFailed: " + id);
+ }
+
+ @Override
+ public void onCaptureSequenceCompleted(CameraCaptureSession session, int
+ sequenceId, long frameNumber) {
+ Log.d(TAG, "captureStillPicture onCaptureSequenceCompleted: " + id);
+ unlockFocus(id);
+ }
+ };
try {
if (null == mActivity || null == mCameraDevice[id]) {
warningToast("Camera is not ready yet to take a picture.");
@@ -951,31 +992,14 @@ public class CaptureModule implements CameraModule, PhotoController,
ClearSightImageProcessor.getInstance().capture(
id==BAYER_ID, mCaptureSession[id], captureBuilder, mCaptureCallbackHandler);
} else if(id == getMainCameraId() && mPostProcessor.isFilterOn()) {
+ mCaptureSession[id].stopRepeating();
captureBuilder.addTarget(mImageReader[id].getSurface());
- List<CaptureRequest> captureList = mPostProcessor.setRequiredImages(captureBuilder);
- mCaptureSession[id].captureBurst(captureList, new CameraCaptureSession.CaptureCallback() {
-
- @Override
- public void onCaptureCompleted(CameraCaptureSession session,
- CaptureRequest request,
- TotalCaptureResult result) {
- Log.d(TAG, "captureStillPicture onCaptureCompleted: " + id);
- }
-
- @Override
- public void onCaptureFailed(CameraCaptureSession session,
- CaptureRequest request,
- CaptureFailure result) {
- Log.d(TAG, "captureStillPicture onCaptureFailed: " + id);
- }
-
- @Override
- public void onCaptureSequenceCompleted(CameraCaptureSession session, int
- sequenceId, long frameNumber) {
- Log.d(TAG, "captureStillPicture onCaptureSequenceCompleted: " + id);
- unlockFocus(id);
- }
- }, mCaptureCallbackHandler);
+ if(mPostProcessor.isManualMode()) {
+ mPostProcessor.manualCapture(captureBuilder, mCaptureSession[id], captureCallback, mCaptureCallbackHandler);
+ } else {
+ List<CaptureRequest> captureList = mPostProcessor.setRequiredImages(captureBuilder);
+ mCaptureSession[id].captureBurst(captureList, captureCallback, mCaptureCallbackHandler);
+ }
} else {
captureBuilder.addTarget(mImageReader[id].getSurface());
mCaptureSession[id].stopRepeating();
@@ -1168,7 +1192,8 @@ public class CaptureModule implements CameraModule, PhotoController,
// No Clearsight
mImageReader[i] = ImageReader.newInstance(mPictureSize.getWidth(),
mPictureSize.getHeight(), imageFormat, MAX_IMAGE_NUM);
- if(mPostProcessor.isFilterOn() && i == getMainCameraId()) {
+ if((mPostProcessor.isFilterOn() || getFrameFilters().size() != 0)
+ && i == getMainCameraId()) {
mImageReader[i].setOnImageAvailableListener(mPostProcessor, mImageAvailableHandler);
} else {
mImageReader[i].setOnImageAvailableListener(new ImageAvailableListener(i) {
@@ -1523,11 +1548,22 @@ public class CaptureModule implements CameraModule, PhotoController,
return filters;
}
+ public void setRefocusLastTaken(final boolean value) {
+ mIsRefocus = value;
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mUI.showRefocusToast(value);
+ }
+ });
+ }
+
private int getPostProcFilterId(int mode) {
if (mode == SettingsManager.SCENE_MODE_OPTIZOOM_INT) {
return PostProcessor.FILTER_OPTIZOOM;
} else if (mode == SettingsManager.SCENE_MODE_NIGHT_INT && SharpshooterFilter.isSupportedStatic()) {
return PostProcessor.FILTER_SHARPSHOOTER;
+ } else if (mode == SettingsManager.SCENE_MODE_UBIFOCUS_INT) {
+ return PostProcessor.FILTER_UBIFOCUS;
}
return PostProcessor.FILTER_NONE;
}
@@ -1563,7 +1599,7 @@ public class CaptureModule implements CameraModule, PhotoController,
mFrameProcessor.onOpen(getFrameProcFilterId());
}
- if(mPostProcessor.isFilterOn()) {
+ if(mPostProcessor.isFilterOn() || getFrameFilters().size() != 0) {
setUpCameraOutputs(ImageFormat.YUV_420_888);
} else {
setUpCameraOutputs(ImageFormat.JPEG);
@@ -2386,7 +2422,8 @@ public class CaptureModule implements CameraModule, PhotoController,
if (seconds > 0) {
mUI.startCountDown(seconds, true);
} else {
- if (mPostProcessor.isFilterOn() && mPostProcessor.isItBusy()) {
+ if((mPostProcessor.isFilterOn() || getFrameFilters().size() != 0)
+ && mPostProcessor.isItBusy()) {
warningToast("It's still busy processing previous scene mode request.");
return;
}
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index cefc77651..30a9425b4 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -42,6 +42,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.camera.imageprocessor.filter.BeautificationFilter;
+import com.android.camera.imageprocessor.filter.TrackingFocusFrameListener;
import com.android.camera.ui.AutoFitSurfaceView;
import com.android.camera.ui.Camera2FaceView;
import com.android.camera.ui.CameraControls;
@@ -61,6 +63,7 @@ import com.android.camera.util.CameraUtil;
import org.codeaurora.snapcam.R;
+import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -97,13 +100,13 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
SettingsManager.KEY_EXPOSURE,
SettingsManager.KEY_WHITE_BALANCE,
SettingsManager.KEY_CAMERA2,
- SettingsManager.KEY_MAKEUP,
SettingsManager.KEY_FACE_DETECTION,
SettingsManager.KEY_VIDEO_FLASH_MODE,
SettingsManager.KEY_VIDEO_DURATION,
SettingsManager.KEY_VIDEO_QUALITY,
- SettingsManager.KEY_TRACKINGFOCUS
- };
+ SettingsManager.KEY_TRACKINGFOCUS,
+ SettingsManager.KEY_MAKEUP
+ };
String[] mDeveloperKeys = new String[]{
SettingsManager.KEY_REDEYE_REDUCTION,
SettingsManager.KEY_MONO_ONLY,
@@ -388,7 +391,7 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
initializeSettingMenu();
initSceneModeButton();
initFilterModeButton();
- if(mTrackingFocusRenderer != null) {
+ if (mTrackingFocusRenderer != null) {
mTrackingFocusRenderer.setVisible(true);
}
}
@@ -1033,7 +1036,6 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
String[] keys = mSettingKeys;
if (mActivity.isDeveloperMenuEnabled()) {
- keys = mDeveloperKeys;
String[] combined = new String[mSettingKeys.length + mDeveloperKeys.length];
int idx = 0;
for (String key: mSettingKeys) {
@@ -1358,6 +1360,10 @@ public class CaptureUI implements FocusOverlayManager.FocusUI,
return ret;
}
+ public void showRefocusToast(boolean show) {
+ mCameraControls.showRefocusToast(show);
+ }
+
private FocusIndicator getFocusIndicator() {
String trackingFocus = mSettingsManager.getValue(SettingsManager.KEY_TRACKINGFOCUS);
if (trackingFocus != null && trackingFocus.equalsIgnoreCase("on")) {
diff --git a/src/com/android/camera/RefocusActivity.java b/src/com/android/camera/RefocusActivity.java
index ae13b484b..599d46656 100644
--- a/src/com/android/camera/RefocusActivity.java
+++ b/src/com/android/camera/RefocusActivity.java
@@ -30,6 +30,7 @@ package com.android.camera;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.OutputStream;
import android.animation.Animator;
@@ -43,6 +44,7 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.net.Uri;
@@ -50,12 +52,15 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Build;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.FrameLayout;
+import com.android.camera.exif.ExifInterface;
+
import org.codeaurora.snapcam.R;
public class RefocusActivity extends Activity {
@@ -77,19 +82,27 @@ public class RefocusActivity extends Activity {
private int mCurrentImage = -1;
private int mRequestedImage = -1;
private LoadImageTask mLoadImageTask;
+ private boolean mMapRotated = false;
+ private int mOrientation = 0;
+ public static final int MAP_ROTATED = 1;
+ private String mFilesPath;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
+ mFilesPath = getFilesDir()+"";
+ if(getIntent().getFlags() == MAP_ROTATED) {
+ mMapRotated = true;
+ mFilesPath = getFilesDir()+"/Ubifocus";
+ }
new Thread(new Runnable() {
public void run() {
- mDepthMap = new DepthMap(getFilesDir() + "/DepthMapImage.y");
+ mDepthMap = new DepthMap(mFilesPath + "/DepthMapImage.y");
}
}).start();
mUri = getIntent().getData();
- setResult(RESULT_CANCELED, new Intent());
setContentView(R.layout.refocus_editor);
mIndicator = (Indicator) findViewById(R.id.refocus_indicator);
@@ -129,6 +142,7 @@ public class RefocusActivity extends Activity {
findViewById(R.id.refocus_cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
+ setResult(RESULT_CANCELED, new Intent());
finish();
}
});
@@ -137,11 +151,12 @@ public class RefocusActivity extends Activity {
@Override
public void onClick(final View v) {
if (mRequestedImage != NAMES.length - 1) {
- new SaveImageTask().execute(getFilesDir() + "/" + NAMES[mRequestedImage]
+ new SaveImageTask().execute(mFilesPath + "/" + NAMES[mRequestedImage]
+ ".jpg");
} else {
finish();
}
+ setResult(RESULT_OK, new Intent());
}
});
@@ -163,7 +178,7 @@ public class RefocusActivity extends Activity {
if (depth != mCurrentImage) {
mCurrentImage = depth;
mLoadImageTask = new LoadImageTask();
- mLoadImageTask.execute(getFilesDir() + "/" + NAMES[depth] + ".jpg");
+ mLoadImageTask.execute(mFilesPath + "/" + NAMES[depth] + ".jpg");
}
}
}
@@ -202,11 +217,16 @@ public class RefocusActivity extends Activity {
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path[0], o);
-
+ ExifInterface exif = new ExifInterface();
+ mOrientation = 0;
+ try {
+ exif.readExif(path[0]);
+ mOrientation = 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;
@@ -215,7 +235,14 @@ public class RefocusActivity extends Activity {
o.inJustDecodeBounds = false;
o.inSampleSize = sample;
- return BitmapFactory.decodeFile(path[0], o);
+ Bitmap bitmap = BitmapFactory.decodeFile(path[0], o);
+ if (mOrientation != 0) {
+ Matrix matrix = new Matrix();
+ matrix.setRotate(mOrientation);
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), matrix, false);
+ }
+ return bitmap;
}
protected void onPostExecute(Bitmap result) {
@@ -258,6 +285,21 @@ public class RefocusActivity extends Activity {
int newX = (int) (x * mWidth);
int newY = (int) (y * mHeight);
+ if(mMapRotated) {
+ if(mOrientation == 0) {
+ newX = (int) (x * mWidth);
+ newY = (int) (y * mHeight);
+ } if(mOrientation == 90) {
+ newX = (int) ((y) * mWidth);
+ newY = (int) ((1 - x) * mHeight);
+ } else if (mOrientation == 180) {
+ newX = (int) ((1-x) * mWidth);
+ newY = (int) ((1-y) * mHeight);
+ } else if (mOrientation == 270) {
+ newX = (int) ((1-y) * mWidth);
+ newY = (int) ((x) * mHeight);
+ }
+ }
int[] hist = new int[256];
for (int i = 0; i < 256; i++) {
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
index b5ac8b3ee..7ab45fbdc 100644
--- a/src/com/android/camera/SettingsManager.java
+++ b/src/com/android/camera/SettingsManager.java
@@ -44,7 +44,10 @@ import android.util.Range;
import android.util.Rational;
import android.util.Size;
+import com.android.camera.imageprocessor.filter.BeautificationFilter;
import com.android.camera.imageprocessor.filter.OptizoomFilter;
+import com.android.camera.imageprocessor.filter.TrackingFocusFrameListener;
+import com.android.camera.imageprocessor.filter.UbifocusFilter;
import com.android.camera.ui.ListMenu;
import com.android.camera.util.SettingTranslation;
@@ -71,6 +74,7 @@ public class SettingsManager implements ListMenu.SettingsListener {
// Custom-Scenemodes start from 100
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 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";
@@ -493,6 +497,8 @@ public class SettingsManager implements ListMenu.SettingsListener {
ListPreference noiseReduction = mPreferenceGroup.findPreference(KEY_NOISE_REDUCTION);
ListPreference videoFlash = mPreferenceGroup.findPreference(KEY_VIDEO_FLASH_MODE);
ListPreference faceDetection = mPreferenceGroup.findPreference(KEY_FACE_DETECTION);
+ ListPreference makeup = mPreferenceGroup.findPreference(KEY_MAKEUP);
+ ListPreference trackingfocus = mPreferenceGroup.findPreference(KEY_TRACKINGFOCUS);
if (whiteBalance != null) {
CameraSettings.filterUnsupportedOptions(mPreferenceGroup,
@@ -568,6 +574,16 @@ public class SettingsManager implements ListMenu.SettingsListener {
if (!isFaceDetectionSupported(cameraId))
removePreference(mPreferenceGroup, KEY_FACE_DETECTION);
}
+
+ if (makeup != null) {
+ if (!BeautificationFilter.isSupportedStatic())
+ removePreference(mPreferenceGroup, KEY_MAKEUP);
+ }
+
+ if (trackingfocus != null) {
+ if (!TrackingFocusFrameListener.isSupportedStatic())
+ removePreference(mPreferenceGroup, KEY_TRACKINGFOCUS);
+ }
}
private void buildExposureCompensation(int cameraId) {
@@ -823,7 +839,8 @@ public class SettingsManager implements ListMenu.SettingsListener {
List<String> modes = new ArrayList<>();
modes.add("0"); // need special case handle for auto scene mode
if (mIsMonoCameraPresent) modes.add(SCENE_MODE_DUAL_STRING); // need special case handle for dual mode
- if (OptizoomFilter.isSupportedStatic()) modes.add(SCENE_MODE_OPTIZOOM_INT + ""); // 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 + "");
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 f39845346..8c0d2ff88 100644
--- a/src/com/android/camera/imageprocessor/PostProcessor.java
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -29,9 +29,12 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.android.camera.imageprocessor;
import android.content.ContentResolver;
+import android.content.Context;
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.CaptureRequest;
import android.media.Image;
import android.media.ImageReader;
@@ -50,9 +53,11 @@ import com.android.camera.SettingsManager;
import com.android.camera.exif.ExifInterface;
import com.android.camera.imageprocessor.filter.OptizoomFilter;
import com.android.camera.imageprocessor.filter.SharpshooterFilter;
+import com.android.camera.imageprocessor.filter.UbifocusFilter;
import com.android.camera.ui.RotateTextToast;
import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -70,7 +75,8 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
public static final int FILTER_NONE = 0;
public static final int FILTER_OPTIZOOM = 1;
public static final int FILTER_SHARPSHOOTER = 2;
- public static final int FILTER_MAX = 3;
+ public static final int FILTER_UBIFOCUS = 3;
+ public static final int FILTER_MAX = 4;
private int mCurrentNumImage = 0;
private ImageFilter mFilter;
@@ -86,6 +92,7 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
private Image[] mImages;
private PhotoModule.NamedImages mNamedImages;
private WatchdogThread mWatchdog;
+ private int mOrientation = 0;
//This is for the debug feature.
private static boolean DEBUG_FILTER = false;
@@ -139,11 +146,17 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
}
}
+ public boolean isManualMode() {
+ return mFilter.isManualMode();
+ }
+
+ public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) throws CameraAccessException {
+ mFilter.manualCapture(builder, captureSession, callback, handler);
+ }
+
public boolean isFilterOn() {
- if(mFilter != null) {
- return true;
- }
- if(mController.getFrameFilters().size() != 0) {
+ if (mFilter != null) {
return true;
}
return false;
@@ -269,6 +282,9 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
case FILTER_SHARPSHOOTER:
mFilter = new SharpshooterFilter(mController);
break;
+ case FILTER_UBIFOCUS:
+ mFilter = new UbifocusFilter(mController, mActivity);
+ break;
}
}
@@ -333,6 +349,7 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
if(mWatchdog != null) {
mWatchdog.startMonitor();
}
+ mOrientation = CameraUtil.getJpegRotation(mController.getMainCameraId(), mController.getDisplayOrientation());
}
if(mFilter != null && mCurrentNumImage >= mFilter.getNumRequiredImage()) {
return;
@@ -374,7 +391,7 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
});
}
- private byte[] addExifTags(byte[] jpeg, int orientationInDegree) {
+ public static byte[] addExifTags(byte[] jpeg, int orientationInDegree) {
ExifInterface exif = new ExifInterface();
exif.addOrientationTag(orientationInDegree);
exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, System.currentTimeMillis(),
@@ -434,17 +451,16 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
) {
Log.e(TAG, "Processed outRoi is not within picture range");
} else {
- int orientation = CameraUtil.getJpegRotation(mController.getMainCameraId(), mController.getDisplayOrientation());
if(mFilter != null && DEBUG_FILTER) {
- bytes = nv21ToJpeg(mDebugResultImage, orientation);
+ bytes = nv21ToJpeg(mDebugResultImage, mOrientation);
mActivity.getMediaSaveService().addImage(
bytes, title + "_beforeApplyingFilter", date, null, mDebugResultImage.outRoi.width(), mDebugResultImage.outRoi.height(),
- orientation, null, mediaSavedListener, contentResolver, "jpeg");
+ mOrientation, null, mediaSavedListener, contentResolver, "jpeg");
}
- bytes = nv21ToJpeg(resultImage, orientation);
+ bytes = nv21ToJpeg(resultImage, mOrientation);
mActivity.getMediaSaveService().addImage(
bytes, title, date, null, resultImage.outRoi.width(), resultImage.outRoi.height(),
- orientation, null, mediaSavedListener, contentResolver, "jpeg");
+ mOrientation, null, mediaSavedListener, contentResolver, "jpeg");
mController.updateThumbnailJpegData(bytes);
}
}
diff --git a/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java b/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java
index 7a13895f4..77e6ead6e 100644
--- a/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/BeautificationFilter.java
@@ -30,8 +30,10 @@ package com.android.camera.imageprocessor.filter;
import android.graphics.Rect;
import android.hardware.Camera;
+import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.Face;
+import android.os.Handler;
import android.util.Log;
import android.util.Size;
@@ -120,11 +122,26 @@ public class BeautificationFilter implements ImageFilter {
return mIsSupported;
}
+ public static boolean isSupportedStatic() {
+ 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) {
+
+ }
+
private native int nativeBeautificationProcess(ByteBuffer yB, ByteBuffer vuB,
int width, int height, int stride, int fleft, int ftop, int fright, int fbottom);
diff --git a/src/com/android/camera/imageprocessor/filter/ImageFilter.java b/src/com/android/camera/imageprocessor/filter/ImageFilter.java
index b778dee03..bb581c965 100644
--- a/src/com/android/camera/imageprocessor/filter/ImageFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/ImageFilter.java
@@ -29,7 +29,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.android.camera.imageprocessor.filter;
import android.graphics.Rect;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CaptureRequest;
+import android.os.Handler;
import java.nio.ByteBuffer;
import java.util.List;
@@ -41,6 +44,7 @@ public interface ImageFilter {
String getStringName();
+ /* This is used for auto mode burst picture */
int getNumRequiredImage();
void init(int width, int height, int strideY, int strideVU);
@@ -72,5 +76,13 @@ public interface ImageFilter {
}
}
+ /* Whether it is post proc filter or frame proc filter */
boolean isFrameListener();
+
+ /* Whether it will use burst capture or manual capture */
+ boolean isManualMode();
+
+ /* if it's manual mode, this function has to be implemented */
+ void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) throws CameraAccessException;
}
diff --git a/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java b/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
index 16b8ae163..486ea7a0c 100644
--- a/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
@@ -29,7 +29,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.android.camera.imageprocessor.filter;
import android.graphics.Rect;
+import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CaptureRequest;
+import android.os.Handler;
import android.util.Log;
import com.android.camera.CaptureModule;
@@ -132,6 +134,16 @@ public class OptizoomFilter implements ImageFilter{
return false;
}
+ @Override
+ public boolean isManualMode() {
+ return false;
+ }
+
+ @Override
+ public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) {
+ }
+
public static boolean isSupportedStatic() {
return mIsSupported;
}
diff --git a/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java b/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java
index e123f3439..c51e13c59 100644
--- a/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java
@@ -29,9 +29,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.android.camera.imageprocessor.filter;
import android.graphics.Rect;
+import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.os.Handler;
import android.util.Log;
import android.util.Range;
import android.util.Rational;
@@ -155,6 +157,17 @@ public class SharpshooterFilter implements ImageFilter{
return false;
}
+ @Override
+ public boolean isManualMode() {
+ return false;
+ }
+
+ @Override
+ public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) {
+
+ }
+
public static boolean isSupportedStatic() {
return mIsSupported;
}
diff --git a/src/com/android/camera/imageprocessor/filter/TrackingFocusFrameListener.java b/src/com/android/camera/imageprocessor/filter/TrackingFocusFrameListener.java
index a12eef91a..8d9a7fc1a 100644
--- a/src/com/android/camera/imageprocessor/filter/TrackingFocusFrameListener.java
+++ b/src/com/android/camera/imageprocessor/filter/TrackingFocusFrameListener.java
@@ -32,8 +32,10 @@ package com.android.camera.imageprocessor.filter;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
+import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.Face;
+import android.os.Handler;
import android.util.Log;
import android.util.Size;
@@ -256,11 +258,26 @@ public class TrackingFocusFrameListener implements ImageFilter {
return mIsSupported;
}
+ public static boolean isSupportedStatic() {
+ return mIsSupported;
+ }
+
@Override
public boolean isFrameListener() {
return true;
}
+ @Override
+ public boolean isManualMode() {
+ return false;
+ }
+
+ @Override
+ public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) {
+
+ }
+
private native int nInit(int operationMode, int precision, int width, int height, int stride);
private native void nRelease();
private native int nGetMinRoiDimension();
diff --git a/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java b/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
new file mode 100644
index 000000000..b410e01b4
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
@@ -0,0 +1,269 @@
+/*
+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.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.Camera;
+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.os.Handler;
+import android.util.Log;
+import android.util.Range;
+
+import com.android.camera.CameraActivity;
+import com.android.camera.CaptureModule;
+import com.android.camera.imageprocessor.PostProcessor;
+import com.android.camera.util.CameraUtil;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class UbifocusFilter implements ImageFilter {
+ public static final int NUM_REQUIRED_IMAGE = 5;
+ private int mWidth;
+ private int mHeight;
+ private int mStrideY;
+ private int mStrideVU;
+ private static String TAG = "UbifocusFilter";
+ private static final boolean DEBUG = true;
+ private static final int FOCUS_ADJUST_TIME_OUT = 200;
+ private static final int META_BYTES_SIZE = 25;
+ private int temp;
+ private static boolean mIsSupported = true;
+ private ByteBuffer mOutBuf;
+ private CaptureModule mModule;
+ private CameraActivity mActivity;
+ private int mOrientation = 0;
+ private float mMinFocusDistance = -1f;
+ final String[] NAMES = {"00.jpg", "01.jpg", "02.jpg", "03.jpg",
+ "04.jpg", "DepthMapImage.y", "AllFocusImage.jpg"};
+
+ private static void Log(String msg) {
+ if (DEBUG) {
+ Log.d(TAG, msg);
+ }
+ }
+
+ public UbifocusFilter(CaptureModule module, CameraActivity activity) {
+ mModule = module;
+ mActivity = activity;
+ }
+
+ @Override
+ public List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder) {
+ return null;
+ }
+
+ @Override
+ public String getStringName() {
+ return "UbifocusFilter";
+ }
+
+ @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;
+ mOutBuf = ByteBuffer.allocate(mStrideY * mHeight * 3 / 2);
+ Log("width: "+mWidth+" height: "+mHeight+" strideY: "+mStrideY+" strideVU: "+mStrideVU);
+ nativeInit(mWidth, mHeight, mStrideY, mStrideVU, NUM_REQUIRED_IMAGE);
+ }
+
+ @Override
+ public void deinit() {
+ Log("deinit");
+ mOutBuf = null;
+ nativeDeinit();
+ }
+
+ @Override
+ public void addImage(ByteBuffer bY, ByteBuffer bVU, int imageNum, Object param) {
+ Log("addImage");
+ if(imageNum == 0) {
+ mModule.setRefocusLastTaken(false);
+ mOrientation = CameraUtil.getJpegRotation(mModule.getMainCameraId(), mModule.getDisplayOrientation());
+ }
+ 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");
+ }
+ }
+
+ @Override
+ public ResultImage processImage() {
+ Log("processImage ");
+ int[] roi = new int[4];
+ int[] depthMapSize = new int[2];
+ int status = nativeProcessImage(mOutBuf.array(), roi, depthMapSize);
+ if(status < 0) { //In failure case, library will return the first image as it is.
+ Log.w(TAG, "Fail to process the "+getStringName());
+ } else {
+ byte[] depthMapBuf = new byte[depthMapSize[0] * depthMapSize[1] + META_BYTES_SIZE];
+ nativeGetDepthMap(depthMapBuf, depthMapSize[0], depthMapSize[1]);
+ saveToPrivateFile(NAMES.length - 2, depthMapBuf);
+ 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);
+ }
+
+ 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;
+ }
+
+ @Override
+ public boolean isSupported() {
+ return mIsSupported;
+ }
+
+ @Override
+ public boolean isFrameListener() {
+ return false;
+ }
+
+ @Override
+ public boolean isManualMode() {
+ return true;
+ }
+
+ @Override
+ public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
+ CameraCaptureSession.CaptureCallback callback, Handler handler) throws CameraAccessException {
+ if (mMinFocusDistance == -1f) {
+ mMinFocusDistance = mModule.getMainCameraCharacteristics().get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+ }
+ float step = mMinFocusDistance / NUM_REQUIRED_IMAGE;
+ for(int i=0; i < NUM_REQUIRED_IMAGE; i++) {
+ float value = (i * step);
+ mModule.setAFModeToPreview(mModule.getMainCameraId(), CaptureRequest.CONTROL_AF_MODE_OFF);
+ mModule.setFocusDistanceToPreview(mModule.getMainCameraId(), value);
+ try {
+ int count = FOCUS_ADJUST_TIME_OUT;
+ do {
+ Thread.sleep(5);
+ count -= 5;
+ if(count <= 0) {
+ break;
+ }
+ } while(Math.abs(mModule.getPreviewCaptureResult().get(CaptureResult.LENS_FOCUS_DISTANCE)
+ - value) >= 0.5f);
+ } catch (InterruptedException e) {
+ }
+ builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
+ builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, value);
+ captureSession.capture(builder.build(), callback, handler);
+ Log.d(TAG, "Request: " + value);
+ }
+ }
+
+ 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) {
+ new Thread() {
+ public void run() {
+ String filesPath = mActivity.getFilesDir()+"/Ubifocus";
+ 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) {
+ }
+ }
+ }.start();
+ }
+
+ private native int nativeInit(int width, int height, int yStride, int vuStride, int numImages);
+ private native int nativeDeinit();
+ private native int nativeAddImage(ByteBuffer yB, ByteBuffer vuB, int ySize, int vuSize, int imageNum);
+ private native int nativeGetDepthMap(byte[] depthMapBuf, int depthMapWidth, int depthMapHeight);
+ private native int nativeProcessImage(byte[] buffer, int[] roi, int[] depthMapSize);
+
+ static {
+ try {
+ System.loadLibrary("jni_ubifocus");
+ mIsSupported = true;
+ }catch(UnsatisfiedLinkError e) {
+ mIsSupported = false;
+ }
+ }
+}