summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Yoo <jyoo@codeaurora.org>2016-05-10 14:11:19 -0700
committerSteve Kondik <steve@cyngn.com>2016-08-21 18:45:51 -0700
commit7f35afc3939acbffeff32c2e419d1e46648fba4c (patch)
treead34c613a9e084b1210d94f7bd6290cf540b8895
parent95a06e0ac119e1e8523db160ddf9666b9c3d8d9b (diff)
downloadandroid_packages_apps_Snap-7f35afc3939acbffeff32c2e419d1e46648fba4c.tar.gz
android_packages_apps_Snap-7f35afc3939acbffeff32c2e419d1e46648fba4c.tar.bz2
android_packages_apps_Snap-7f35afc3939acbffeff32c2e419d1e46648fba4c.zip
SnapdragonCamera: Sharpshooter post filter
Adding Sharpshooter post process filter Change-Id: I8f3c1962db437e7dfbe2973f806a3f9a26480eb7 CRs-Fixed: 1023183
-rw-r--r--rs/YuvToRgb.rs6
-rw-r--r--rs/rotator.rs24
-rw-r--r--src/com/android/camera/CaptureModule.java59
-rw-r--r--src/com/android/camera/SettingsManager.java2
-rw-r--r--src/com/android/camera/exif/ExifInterface.java17
-rw-r--r--src/com/android/camera/imageprocessor/FrameProcessor.java8
-rw-r--r--src/com/android/camera/imageprocessor/PostProcessor.java46
-rw-r--r--src/com/android/camera/imageprocessor/filter/OptizoomFilter.java2
-rw-r--r--src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java172
9 files changed, 299 insertions, 37 deletions
diff --git a/rs/YuvToRgb.rs b/rs/YuvToRgb.rs
index 25771c5c7..57076e979 100644
--- a/rs/YuvToRgb.rs
+++ b/rs/YuvToRgb.rs
@@ -41,9 +41,9 @@ uchar4 __attribute__((kernel)) nv21ToRgb(uint32_t x, uint32_t y) {
int vV = (int)(rsGetElementAt_uchar(gIn, index) & 0xFF ) -128;
int uV = (int)(rsGetElementAt_uchar(gIn, index+1) & 0xFF ) -128;
- int r = (int) (1.164f * yV + 1.596f * vV );
- int g = (int) (1.164f * yV - 0.813f * vV - 0.391f * uV);
- int b = (int) (1.164f * yV + 2.018f * uV );
+ int r = (int) (yV + 1.370705f * vV );
+ int g = (int) (yV - 0.698001f * vV - 0.337633f* uV);
+ int b = (int) (yV + 1.732446 * uV );
r = r>255? 255 : r<0 ? 0 : r;
g = g>255? 255 : g<0 ? 0 : g;
diff --git a/rs/rotator.rs b/rs/rotator.rs
index cd9da4396..5a27e00f7 100644
--- a/rs/rotator.rs
+++ b/rs/rotator.rs
@@ -34,18 +34,34 @@ rs_allocation gOut;
rs_allocation gIn;
uint32_t width;
uint32_t height;
+uint32_t pad;
+bool gFlip;
uchar __attribute__((kernel)) rotate90andMerge(uint32_t x, uint32_t y) {
uchar yValue = rsGetElementAt_uchar(gIn, x + y*width);
- rsSetElementAt_uchar(gOut, yValue, x*height + height - 1 - y);
- if(x%2 == 0 && y%2==1) {
+ if(gFlip) {
+ if(x >= width - pad)
+ return (uchar)0;
+ rsSetElementAt_uchar(gOut, yValue, (width-1-x-pad)*height + height - 1 - y);
+ } else {
+ rsSetElementAt_uchar(gOut, yValue, x*height + height - 1 - y);
+ }
+
+ if(x%2 == 0 && y%2 == 0) {
uint32_t ySize = width*height;
uint32_t index = ySize + x + ((y/2) * width);
uchar vValue = rsGetElementAt_uchar(gIn, index);
uchar uValue = rsGetElementAt_uchar(gIn, index + 1);
- rsSetElementAt_uchar(gOut, vValue, ySize + x/2*height + height - 1 - y);
- rsSetElementAt_uchar(gOut, uValue, ySize + x/2*height + height - 1 - y - 1);
+ if(gFlip) {
+ if(x >= width - pad)
+ return (uchar)0;
+ rsSetElementAt_uchar(gOut, uValue, ySize + (width-2-x-pad)/2*height + height - 1 - y);
+ rsSetElementAt_uchar(gOut, vValue, ySize + (width-2-x-pad)/2*height + height - 1 - y - 1);
+ } else {
+ rsSetElementAt_uchar(gOut, uValue, ySize + x/2*height + height - 1 - y);
+ rsSetElementAt_uchar(gOut, vValue, ySize + x/2*height + height - 1 - y - 1);
+ }
}
return (uchar)0;
} \ No newline at end of file
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 0f65f21c3..9d09343ea 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -68,6 +68,7 @@ import com.android.camera.imageprocessor.PostProcessor;
import com.android.camera.imageprocessor.FrameProcessor;
import com.android.camera.PhotoModule.NamedImages;
import com.android.camera.PhotoModule.NamedImages.NamedEntity;
+import com.android.camera.imageprocessor.filter.SharpshooterFilter;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.ui.RotateTextToast;
@@ -187,6 +188,7 @@ public class CaptureModule implements CameraModule, PhotoController,
private SettingsManager mSettingsManager;
private long SECONDARY_SERVER_MEM;
private boolean mLongshotActive = false;
+ private CameraCharacteristics mMainCameraCharacteristics;
/**
* A {@link CameraCaptureSession } for camera preview.
@@ -205,6 +207,7 @@ public class CaptureModule implements CameraModule, PhotoController,
private PostProcessor mPostProcessor;
private FrameProcessor mFrameProcessor;
private Size mFrameProcPreviewOutputSize;
+ private CaptureResult mPreviewCaptureResult;
private Face[] mPreviewFaces = null;
private Face[] mStickyFaces = null;
private Rect mBayerCameraRegion;
@@ -323,6 +326,10 @@ public class CaptureModule implements CameraModule, PhotoController,
return mStickyFaces;
}
+ public CaptureResult getPreviewCaptureResult() {
+ return mPreviewCaptureResult;
+ }
+
public Rect getCameraRegion() {
return mBayerCameraRegion;
}
@@ -351,6 +358,7 @@ public class CaptureModule implements CameraModule, PhotoController,
if(faces != null && faces.length != 0) {
mStickyFaces = faces;
}
+ mPreviewCaptureResult = result;
switch (mState[id]) {
case STATE_PREVIEW: {
@@ -492,7 +500,7 @@ public class CaptureModule implements CameraModule, PhotoController,
else return false;
}
- private boolean isBackCamera() {
+ public boolean isBackCamera() {
String value = mSettingsManager.getValue(SettingsManager.KEY_CAMERA_ID);
if (value == null) return true;
if (Integer.parseInt(value) == BAYER_ID) return true;
@@ -1027,6 +1035,11 @@ public class CaptureModule implements CameraModule, PhotoController,
mFrameProcPreviewOutputSize = sizeList.get(i);
}
}
+
+ public CameraCharacteristics getMainCameraCharacteristics() {
+ return mMainCameraCharacteristics;
+ }
+
/**
* Sets up member variables related to camera.
*
@@ -1047,6 +1060,7 @@ public class CaptureModule implements CameraModule, PhotoController,
if(i == getMainCameraId()) {
mBayerCameraRegion = characteristics.get(CameraCharacteristics
.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ mMainCameraCharacteristics = characteristics;
}
StreamConfigurationMap map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
@@ -1364,23 +1378,15 @@ public class CaptureModule implements CameraModule, PhotoController,
return filters;
}
- private int getPostProcFilterId() {
- String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
- if (scene != null) {
- int mode = Integer.parseInt(scene);
- if (mode == SettingsManager.SCENE_MODE_OPTIZOOM_INT)
- return PostProcessor.FILTER_OPTIZOOM;
+ 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;
}
return PostProcessor.FILTER_NONE;
}
- private boolean isPostProcFilter(String value) {
- if(value.equalsIgnoreCase(SettingsManager.SCENE_MODE_OPTIZOOM_INT+"")) {
- return true;
- }
- return false;
- }
-
@Override
public void onResumeAfterSuper() {
Log.d(TAG, "onResume " + getCameraMode());
@@ -1388,12 +1394,19 @@ public class CaptureModule implements CameraModule, PhotoController,
mUI.setSwitcherIndex();
mCameraIdList = new ArrayList<>();
if(mPostProcessor != null) {
- Log.d(TAG, "Chosen postproc filter id : "+getPostProcFilterId());
- mPostProcessor.onOpen(getPostProcFilterId());
+ String scene = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
+ if (scene != null) {
+ int mode = Integer.parseInt(scene);
+ Log.d(TAG, "Chosen postproc filter id : " + getPostProcFilterId(mode));
+ mPostProcessor.onOpen(getPostProcFilterId(mode));
+ } else {
+ mPostProcessor.onOpen(PostProcessor.FILTER_NONE);
+ }
}
if(mFrameProcessor != null) {
mFrameProcessor.onOpen(getFrameProcFilterId());
}
+
if(mPostProcessor.isFilterOn()) {
setUpCameraOutputs(ImageFormat.YUV_420_888);
} else {
@@ -1575,7 +1588,7 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
- private int getMainCameraId() {
+ public int getMainCameraId() {
if (isBackCamera()) {
switch (getCameraMode()) {
case DUAL_MODE:
@@ -1664,6 +1677,7 @@ public class CaptureModule implements CameraModule, PhotoController,
@Override
public void onPreviewUIDestroyed() {
+ mSurfaceReady = false;
}
@Override
@@ -1700,6 +1714,10 @@ public class CaptureModule implements CameraModule, PhotoController,
}
}
+ public int getDisplayOrientation() {
+ return mOrientation;
+ }
+
@Override
public void onShowSwitcherPopup() {
@@ -1959,6 +1977,10 @@ public class CaptureModule implements CameraModule, PhotoController,
String value = mSettingsManager.getValue(SettingsManager.KEY_SCENE_MODE);
if (value == null) return;
int mode = Integer.parseInt(value);
+ if(getPostProcFilterId(mode) != PostProcessor.FILTER_NONE) {
+ request.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ return;
+ }
if (mode != CaptureRequest.CONTROL_SCENE_MODE_DISABLED && mode !=
SettingsManager.SCENE_MODE_DUAL_INT) {
request.set(CaptureRequest.CONTROL_SCENE_MODE, mode);
@@ -2203,7 +2225,8 @@ public class CaptureModule implements CameraModule, PhotoController,
private boolean checkNeedToRestart(String value) {
mPostProcessor.setFilter(PostProcessor.FILTER_NONE);
- if (isPostProcFilter(value))
+ int mode = Integer.parseInt(value);
+ if (getPostProcFilterId(mode) != PostProcessor.FILTER_NONE)
return true;
if (value.equals(SettingsManager.SCENE_MODE_DUAL_STRING) && mCurrentMode != DUAL_MODE)
return true;
diff --git a/src/com/android/camera/SettingsManager.java b/src/com/android/camera/SettingsManager.java
index 215ab8436..1433f1cd0 100644
--- a/src/com/android/camera/SettingsManager.java
+++ b/src/com/android/camera/SettingsManager.java
@@ -58,6 +58,8 @@ import java.util.Set;
public class SettingsManager implements ListMenu.SettingsListener {
public static final int RESOURCE_TYPE_THUMBNAIL = 0;
public static final int RESOURCE_TYPE_LARGEICON = 1;
+ public static final int SCENE_MODE_NIGHT_INT = 5;
+
// Custom-Scenemodes start from 100
public static final int SCENE_MODE_DUAL_INT = 100;
public static final int SCENE_MODE_OPTIZOOM_INT = 101;
diff --git a/src/com/android/camera/exif/ExifInterface.java b/src/com/android/camera/exif/ExifInterface.java
index 2fec1bf4f..773518821 100644
--- a/src/com/android/camera/exif/ExifInterface.java
+++ b/src/com/android/camera/exif/ExifInterface.java
@@ -1978,6 +1978,23 @@ public class ExifInterface {
return true;
}
+ public boolean addOrientationTag(int orientation) {
+ int value = Orientation.TOP_LEFT;
+ if(orientation == 90) {
+ value = Orientation.RIGHT_TOP;
+ } else if(orientation == 180) {
+ value = Orientation.BOTTOM_LEFT;
+ } else if(orientation == 270) {
+ value = Orientation.RIGHT_BOTTOM;
+ }
+ ExifTag t = buildTag(TAG_ORIENTATION, value);
+ if (t == null) {
+ return false;
+ }
+ setTag(t);
+ return true;
+ }
+
/**
* Creates and sets all to the GPS tags for a give latitude and longitude.
*
diff --git a/src/com/android/camera/imageprocessor/FrameProcessor.java b/src/com/android/camera/imageprocessor/FrameProcessor.java
index 951479de9..6a2091158 100644
--- a/src/com/android/camera/imageprocessor/FrameProcessor.java
+++ b/src/com/android/camera/imageprocessor/FrameProcessor.java
@@ -128,7 +128,7 @@ public class FrameProcessor {
}
}
- private void createAllocation(int width, int height) {
+ private void createAllocation(int width, int height, int stridePad) {
Type.Builder yuvTypeBuilder = new Type.Builder(mRs, Element.YUV(mRs));
yuvTypeBuilder.setX(width);
yuvTypeBuilder.setY(height);
@@ -141,6 +141,8 @@ public class FrameProcessor {
mRsRotator.set_gOut(mProcessAllocation);
mRsRotator.set_width(width);
mRsRotator.set_height(height);
+ mRsRotator.set_pad(stridePad);
+ mRsRotator.set_gFlip(!mModule.isBackCamera());
mRsYuvToRGB.set_gIn(mProcessAllocation);
mRsYuvToRGB.set_width(height);
mRsYuvToRGB.set_height(width);
@@ -266,6 +268,7 @@ public class FrameProcessor {
int ySize;
int stride;
int height;
+ int width;
public ProcessingTask() {
}
@@ -288,6 +291,7 @@ public class FrameProcessor {
ByteBuffer bVU = image.getPlanes()[2].getBuffer();
if(yvuBytes == null) {
stride = image.getPlanes()[0].getRowStride();
+ width = mSize.getWidth();
height = mSize.getHeight();
ySize = stride * mSize.getHeight();
yvuBytes = new byte[ySize*3/2];
@@ -314,7 +318,7 @@ public class FrameProcessor {
return;
}
if(mInputAllocation == null) {
- createAllocation(stride, height);
+ createAllocation(stride, height, stride-width);
}
mInputAllocation.copyFrom(yvuBytes);
mRsRotator.forEach_rotate90andMerge(mInputAllocation);
diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java
index a126e8817..f39845346 100644
--- a/src/com/android/camera/imageprocessor/PostProcessor.java
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -43,17 +43,24 @@ import android.widget.Toast;
import com.android.camera.CameraActivity;
import com.android.camera.CaptureModule;
+import com.android.camera.Exif;
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.OptizoomFilter;
+import com.android.camera.imageprocessor.filter.SharpshooterFilter;
import com.android.camera.ui.RotateTextToast;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
+import java.util.TimeZone;
+
import com.android.camera.imageprocessor.filter.ImageFilter;
+import com.android.camera.util.CameraUtil;
public class PostProcessor implements ImageReader.OnImageAvailableListener{
@@ -62,7 +69,8 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
private static final String TAG = "PostProcessor";
public static final int FILTER_NONE = 0;
public static final int FILTER_OPTIZOOM = 1;
- public static final int FILTER_MAX = 2;
+ public static final int FILTER_SHARPSHOOTER = 2;
+ public static final int FILTER_MAX = 3;
private int mCurrentNumImage = 0;
private ImageFilter mFilter;
@@ -80,7 +88,7 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
private WatchdogThread mWatchdog;
//This is for the debug feature.
- private static boolean DEBUG_FILTER = true; //TODO: This has to be false before releasing.
+ private static boolean DEBUG_FILTER = false;
private ImageFilter.ResultImage mDebugResultImage;
@Override
@@ -258,6 +266,9 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
case FILTER_OPTIZOOM:
mFilter = new OptizoomFilter(mController);
break;
+ case FILTER_SHARPSHOOTER:
+ mFilter = new SharpshooterFilter(mController);
+ break;
}
}
@@ -363,6 +374,20 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{
});
}
+ private byte[] addExifTags(byte[] jpeg, int orientationInDegree) {
+ ExifInterface exif = new ExifInterface();
+ exif.addOrientationTag(orientationInDegree);
+ exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, System.currentTimeMillis(),
+ TimeZone.getDefault());
+ ByteArrayOutputStream jpegOut = new ByteArrayOutputStream();
+ try {
+ exif.writeExif(jpeg, jpegOut);
+ } catch (IOException e) {
+ Log.e(TAG, "Could not write EXIF", e);
+ }
+ return jpegOut.toByteArray();
+ }
+
private void clear() {
mCurrentNumImage = 0;
}
@@ -409,29 +434,32 @@ 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);
+ bytes = nv21ToJpeg(mDebugResultImage, orientation);
mActivity.getMediaSaveService().addImage(
bytes, title + "_beforeApplyingFilter", date, null, mDebugResultImage.outRoi.width(), mDebugResultImage.outRoi.height(),
- 0, null, mediaSavedListener, contentResolver, "jpeg");
+ orientation, null, mediaSavedListener, contentResolver, "jpeg");
}
- bytes = nv21ToJpeg(resultImage);
- mController.updateThumbnailJpegData(bytes);
+ bytes = nv21ToJpeg(resultImage, orientation);
mActivity.getMediaSaveService().addImage(
bytes, title, date, null, resultImage.outRoi.width(), resultImage.outRoi.height(),
- 0, null, mediaSavedListener, contentResolver, "jpeg");
+ orientation, null, mediaSavedListener, contentResolver, "jpeg");
+ mController.updateThumbnailJpegData(bytes);
}
}
}
});
}
- private byte[] nv21ToJpeg(ImageFilter.ResultImage resultImage) {
+ private byte[] nv21ToJpeg(ImageFilter.ResultImage resultImage, int orientation) {
BitmapOutputStream bos = new BitmapOutputStream(1024);
YuvImage im = new YuvImage(resultImage.outBuffer.array(), ImageFormat.NV21,
resultImage.width, resultImage.height, new int[]{resultImage.stride, resultImage.stride});
im.compressToJpeg(resultImage.outRoi, 50, bos);
- return bos.getArray();
+ byte[] bytes = bos.getArray();
+ bytes = addExifTags(bytes, orientation);
+ return bytes;
}
private class BitmapOutputStream extends ByteArrayOutputStream {
diff --git a/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java b/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
index 4773418de..9b5af29dc 100644
--- a/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/OptizoomFilter.java
@@ -45,7 +45,7 @@ public class OptizoomFilter implements ImageFilter{
private int mStrideY;
private int mStrideVU;
private static String TAG = "OptizoomFilter";
- private static final boolean DEBUG = true; //TODO: Have to be false before releasing.
+ private static final boolean DEBUG = false;
private int temp;
private static boolean mIsSupported = true;
private ByteBuffer mOutBuf;
diff --git a/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java b/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java
new file mode 100644
index 000000000..74469afc3
--- /dev/null
+++ b/src/com/android/camera/imageprocessor/filter/SharpshooterFilter.java
@@ -0,0 +1,172 @@
+/*
+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.graphics.Rect;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Log;
+import android.util.Range;
+import android.util.Rational;
+
+import com.android.camera.CaptureModule;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SharpshooterFilter 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 = "SharpshooterFilter";
+ private static final boolean DEBUG = false;
+ private int temp;
+ private static boolean mIsSupported = true;
+ private ByteBuffer mOutBuf;
+ private CaptureModule mModule;
+ private int mSenseValue = 0;
+ private long mExpoTime;
+
+ private static void Log(String msg) {
+ if(DEBUG) {
+ Log.d(TAG, msg);
+ }
+ }
+
+ public SharpshooterFilter(CaptureModule module) {
+ mModule = module;
+ }
+
+ private void getSenseUpperValue() {
+ if(mSenseValue == 0) {
+ Range<Integer> sensRange = mModule.getMainCameraCharacteristics().get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
+ mSenseValue = sensRange.getUpper();
+ }
+ }
+ @Override
+ public List<CaptureRequest> setRequiredImages(CaptureRequest.Builder builder) {
+ getSenseUpperValue();
+ mExpoTime = (mModule.getPreviewCaptureResult().get(CaptureResult.SENSOR_EXPOSURE_TIME)/2);
+ int isoValue = (mModule.getPreviewCaptureResult().get(CaptureResult.SENSOR_SENSITIVITY)).intValue()*2;
+ if(isoValue < mSenseValue) {
+ mSenseValue = isoValue;
+ }
+
+ List<CaptureRequest> list = new ArrayList<CaptureRequest>();
+ for(int i=0; i < NUM_REQUIRED_IMAGE; i++) {
+ builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
+ builder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, new Long(mExpoTime));
+ builder.set(CaptureRequest.SENSOR_SENSITIVITY, mSenseValue);
+ list.add(builder.build());
+ }
+ return list;
+ }
+
+ @Override
+ public String getStringName() {
+ return "SharpshooterFilter";
+ }
+
+ @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,
+ 0, 0, mWidth, mHeight, 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");
+ int yActualSize = bY.remaining();
+ int vuActualSize = bVU.remaining();
+ int status = nativeAddImage(bY, bVU, yActualSize, vuActualSize, imageNum);
+ if(status != 0) {
+ Log.e(TAG, "Fail to add image");
+ }
+ }
+
+ @Override
+ public ResultImage processImage() {
+ Log("processImage ");
+ int[] roi = new int[4];
+ int status = nativeProcessImage(mOutBuf.array(), (int) (mExpoTime / 1000000), mSenseValue, roi);
+ Log("processImage done");
+ if(status < 0) { //In failure case, library will return the first image as it is.
+ Log.w(TAG, "Fail to process the image.");
+ }
+ return new ResultImage(mOutBuf, new Rect(roi[0], roi[1], roi[0]+roi[2], roi[1] + roi[3]), mWidth, mHeight, mStrideY);
+ }
+
+ @Override
+ public boolean isSupported() {
+ return mIsSupported;
+ }
+
+ public static boolean isSupportedStatic() {
+ return mIsSupported;
+ }
+
+ private native int nativeInit(int width, int height, int yStride, int vuStride,
+ int roiX, int roiY, int roiW, int roiH, int numImages);
+ private native int nativeDeinit();
+ private native int nativeAddImage(ByteBuffer yB, ByteBuffer vuB, int ySize, int vuSize, int imageNum);
+ private native int nativeProcessImage(byte[] buffer, int expoTime, int isoValue, int[] roi);
+
+ static {
+ try {
+ System.loadLibrary("jni_sharpshooter");
+ mIsSupported = true;
+ }catch(UnsatisfiedLinkError e) {
+ Log.d(TAG, e.toString());
+ mIsSupported = false;
+ }
+ }
+}