summaryrefslogtreecommitdiffstats
path: root/src/org/codeaurora/snapcam/filter
diff options
context:
space:
mode:
authorweijiew <weijiew@codeaurora.org>2017-02-16 11:20:37 +0800
committerweijiew <weijiew@codeaurora.org>2017-03-08 13:18:13 +0800
commitd72bad4bf46a1cbc49ff1685aac8a3c58c4d7546 (patch)
tree4f494d83199b60b18574b9acba3c7f1061d453be /src/org/codeaurora/snapcam/filter
parentfb7a974380cf55206f546ffba5ee58d9b607d409 (diff)
downloadandroid_packages_apps_Snap-d72bad4bf46a1cbc49ff1685aac8a3c58c4d7546.tar.gz
android_packages_apps_Snap-d72bad4bf46a1cbc49ff1685aac8a3c58c4d7546.tar.bz2
android_packages_apps_Snap-d72bad4bf46a1cbc49ff1685aac8a3c58c4d7546.zip
SnapdragonCamera: FR40621 ClearSight/DDM integrate
ClearSight/DDM, integrate Clear Sight in Camera Framework CRs-Fixed: 1108837 Change-Id: Ibde73b15c9361294eb2e0e05967763005a4546e0
Diffstat (limited to 'src/org/codeaurora/snapcam/filter')
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java329
-rw-r--r--src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java4
-rw-r--r--src/org/codeaurora/snapcam/filter/DDMNativeEngine.java396
-rw-r--r--src/org/codeaurora/snapcam/filter/GDepth.java307
-rw-r--r--src/org/codeaurora/snapcam/filter/GImage.java68
5 files changed, 1060 insertions, 44 deletions
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
index bfd58db28..8a6e7667f 100755..100644
--- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,6 +30,10 @@
package org.codeaurora.snapcam.filter;
import java.io.ByteArrayOutputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -38,8 +42,11 @@ import java.util.List;
import org.codeaurora.snapcam.filter.ClearSightNativeEngine.CamSystemCalibrationData;
import org.codeaurora.snapcam.filter.ClearSightNativeEngine.ClearsightImage;
+import org.codeaurora.snapcam.filter.DDMNativeEngine;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
@@ -80,6 +87,7 @@ import com.android.camera.PhotoModule.NamedImages.NamedEntity;
import com.android.camera.Storage;
import com.android.camera.util.CameraUtil;
+
public class ClearSightImageProcessor {
private static final String TAG = "ClearSightImageProcessor";
private static final String PERSIST_TIMESTAMP_LIMIT_KEY = "persist.camera.cs.threshold";
@@ -87,6 +95,7 @@ public class ClearSightImageProcessor {
private static final String PERSIST_DUMP_FRAMES_KEY = "persist.camera.cs.dumpframes";
private static final String PERSIST_DUMP_YUV_KEY = "persist.camera.cs.dumpyuv";
private static final String PERSIST_CS_TIMEOUT_KEY = "persist.camera.cs.timeout";
+ private static final String PERSIST_DUMP_DEPTH_KEY = "persist.camera.cs.dumpdepth";
private static final long DEFAULT_TIMESTAMP_THRESHOLD_MS = 10;
private static final int DEFAULT_IMAGES_TO_BURST = 4;
@@ -106,6 +115,9 @@ public class ClearSightImageProcessor {
private static final int MSG_NEW_REPROC_RESULT = 4;
private static final int MSG_NEW_REPROC_FAIL = 5;
private static final int MSG_END_CAPTURE = 6;
+ private static final int MSG_CALIBRATION_DATA = 7;
+ private static final int MSG_NEW_LENS_FOCUS_DISTANCE_BAYER = 8;
+ private static final int MSG_NEW_DEPTH = 9;
private static final int CAM_TYPE_BAYER = 0;
private static final int CAM_TYPE_MONO = 1;
@@ -115,6 +127,10 @@ public class ClearSightImageProcessor {
new CameraCharacteristics.Key<>(
"org.codeaurora.qcamera3.dualcam_calib_meta_data.dualcam_calib_meta_data_blob",
byte[].class);
+ private CaptureResult.Key<byte[]> SCALE_CROP_ROTATION_REPROCESS_BLOB =
+ new CaptureResult.Key<byte[]>(
+ "org.codeaurora.qcamera3.hal_private_data.reprocess_data_blob",
+ byte[].class);
private NamedImages mNamedImages;
private ImageReader[] mImageReader = new ImageReader[NUM_CAM];
@@ -128,10 +144,13 @@ public class ClearSightImageProcessor {
private ClearsightRegisterHandler mClearsightRegisterHandler;
private ClearsightProcessHandler mClearsightProcessHandler;
private ImageEncodeHandler mImageEncodeHandler;
+ private DepthProcessHandler mDepthProcessHandler;
+
private HandlerThread mImageProcessThread;
private HandlerThread mClearsightRegisterThread;
private HandlerThread mClearsightProcessThread;
private HandlerThread mImageEncodeThread;
+ private HandlerThread mDepthProcessThread;
private Callback mCallback;
private CameraCaptureSession[] mCaptureSessions = new CameraCaptureSession[NUM_CAM];
@@ -144,6 +163,7 @@ public class ClearSightImageProcessor {
private int mCsTimeout;
private boolean mDumpImages;
private boolean mDumpYUV;
+ private boolean mDumpDepth;
private boolean mIsClosing;
private int mFinishReprocessNum;
@@ -167,8 +187,12 @@ public class ClearSightImageProcessor {
mDumpYUV = SystemProperties.getBoolean(PERSIST_DUMP_YUV_KEY, false);
Log.d(TAG, "mDumpYUV: " + mDumpYUV);
+ mDumpDepth = SystemProperties.getBoolean(PERSIST_DUMP_DEPTH_KEY, false);
+ Log.d(TAG, "mDumpDepth: " + mDumpDepth);
+
mCsTimeout = SystemProperties.getInt(PERSIST_CS_TIMEOUT_KEY, DEFAULT_CS_TIMEOUT_MS);
Log.d(TAG, "mCsTimeout: " + mCsTimeout);
+
}
public static void createInstance() {
@@ -197,11 +221,14 @@ public class ClearSightImageProcessor {
mClearsightProcessThread.start();
mImageEncodeThread = new HandlerThread("CameraImageEncode");
mImageEncodeThread.start();
+ mDepthProcessThread = new HandlerThread("DepthProcess");
+ mDepthProcessThread.start();
mImageProcessHandler = new ImageProcessHandler(mImageProcessThread.getLooper());
mClearsightRegisterHandler = new ClearsightRegisterHandler(mClearsightRegisterThread.getLooper());
mClearsightProcessHandler = new ClearsightProcessHandler(mClearsightProcessThread.getLooper());
mImageEncodeHandler = new ImageEncodeHandler(mImageEncodeThread.getLooper());
+ mDepthProcessHandler = new DepthProcessHandler(mImageEncodeThread.getLooper());
mFinalPictureSize = new Size(width, height);
mFinalPictureRatio = (float)width / (float)height;
@@ -219,8 +246,11 @@ public class ClearSightImageProcessor {
try {
CameraCharacteristics cc = cm.getCameraCharacteristics("0");
byte[] blob = cc.get(OTP_CALIB_BLOB);
+ CamSystemCalibrationData calibrationData = CamSystemCalibrationData.createFromBytes(blob);
ClearSightNativeEngine.getInstance().init(mNumFrameCount*2,
- maxWidth, maxHeight, CamSystemCalibrationData.createFromBytes(blob));
+ maxWidth, maxHeight, calibrationData);
+ mDepthProcessHandler.obtainMessage(MSG_CALIBRATION_DATA,0, 0,
+ calibrationData).sendToTarget();
} catch (CameraAccessException e) {
e.printStackTrace();
}
@@ -281,6 +311,17 @@ public class ClearSightImageProcessor {
}
}
+ if ( mDepthProcessThread != null ) {
+ mDepthProcessThread.quit();
+ try{
+ mDepthProcessThread.join();
+ mDepthProcessThread = null;
+ mDepthProcessHandler = null;
+ }catch (InterruptedException e){
+ e.printStackTrace();
+ }
+ }
+
for(int i=0; i<mImageReader.length; i++) {
if (null != mImageReader[i]) {
mImageReader[i].close();
@@ -356,9 +397,16 @@ public class ClearSightImageProcessor {
Log.d(TAG, "capture - onCaptureCompleted: " + cam);
if(isClosing())
Log.d(TAG, "capture - onCaptureCompleted - closing");
- else
+ else {
mImageProcessHandler.obtainMessage(MSG_NEW_CAPTURE_RESULT,
cam, 0, result).sendToTarget();
+ if (cam == CAM_TYPE_BAYER) {
+ float lensFocusDistance = result.get(CaptureResult.LENS_FOCUS_DISTANCE);
+ Log.d(TAG, "lensFocusDistance=" + lensFocusDistance);
+ mDepthProcessHandler.obtainMessage(MSG_NEW_LENS_FOCUS_DISTANCE_BAYER,
+ 0, 0, lensFocusDistance).sendToTarget();
+ }
+ }
}
@Override
@@ -492,6 +540,7 @@ public class ClearSightImageProcessor {
mNamedEntity = mNamedImages.getNextNameEntity();
mClearsightRegisterHandler.obtainMessage(MSG_START_CAPTURE,
0, 0, mNamedEntity).sendToTarget();
+ mDepthProcessHandler.obtainMessage(MSG_START_CAPTURE).sendToTarget();
break;
case MSG_END_CAPTURE:
// TIMED OUT WAITING FOR FRAME
@@ -832,6 +881,8 @@ public class ClearSightImageProcessor {
// reference not yet set
Log.d(TAG, "reprocess - setReferenceResult: " + msg.obj);
ClearSightNativeEngine.getInstance().setReferenceResult(isBayer, result);
+ mDepthProcessHandler.obtainMessage(MSG_NEW_REPROC_RESULT, msg.arg1, 0, msg.obj)
+ .sendToTarget();
}
mFinishReprocessNum++;
checkReprocessDone();
@@ -912,6 +963,7 @@ public class ClearSightImageProcessor {
.hasReferenceImage(isBayer)) {
// reference not yet set
ClearSightNativeEngine.getInstance().setReferenceImage(isBayer, image);
+ mDepthProcessHandler.obtainMessage(MSG_NEW_IMG, msg.arg1, 0, msg.obj).sendToTarget();
} else {
// if ref images set, register this image
if(ClearSightNativeEngine.getInstance().registerImage(
@@ -960,9 +1012,6 @@ public class ClearSightImageProcessor {
ClearSightNativeEngine.getInstance().reset();
if(processInit) {
- if(mCallback != null)
- mCallback.onReleaseShutterLock();
-
Image encodeImage = mImageWriter[CAM_TYPE_BAYER].dequeueInputImage();
ClearSightNativeEngine.ClearsightImage csImage = new ClearsightImage(encodeImage);
encodeImage.setTimestamp(csTs);
@@ -1086,13 +1135,19 @@ public class ClearSightImageProcessor {
private short mEncodeRequest;
private short mEncodeResults;
- private boolean mReadyToSave;
private boolean mHasFailure;
private Image mMonoImage;
private Image mBayerImage;
private Image mClearSightImage;
private NamedEntity mNamedEntity;
+ private GDepth.DepthMap mDepthMap;
+ private GImage mGImage;
+ private boolean mDepthMapReady;
+ private boolean mClearSightReady;
+
+ private long CLEAR_SIGHT_IMAGE_SAVE_DELAY = 1*500;
+
public ImageEncodeHandler(Looper looper) {
super(looper);
}
@@ -1110,15 +1165,19 @@ public class ClearSightImageProcessor {
Log.d(TAG, "ImageEncodeEvent - END_CAPTURE");
mNamedEntity = (NamedEntity) msg.obj;
mEncodeRequest = (short)msg.arg1;
- mReadyToSave = true;
- saveMpoImage();
+ mClearSightReady = true;
+ saveClearSightImage();
break;
case MSG_NEW_IMG:
case MSG_NEW_CAPTURE_RESULT:
case MSG_NEW_CAPTURE_FAIL:
processNewEvent(msg);
- saveMpoImage();
+ saveClearSightImage();
break;
+ case MSG_NEW_DEPTH:
+ processNewGDepth(msg);
+ saveClearSightImage();
+ break;
}
}
@@ -1128,12 +1187,20 @@ public class ClearSightImageProcessor {
if(msg.arg1 == CAM_TYPE_MONO) {
mMonoImage = (Image)msg.obj;
mEncodeResults |= MASK_MONO_ENCODE;
+ if ( mDumpDepth ) {
+ saveToFile(getJpegData(mMonoImage), "mono", "jpg");
+ }
} else if(mBayerImage == null){
mBayerImage = (Image)msg.obj;
mEncodeResults |= MASK_BAYER_ENCODE;
+ mGImage = new GImage(getJpegData(mBayerImage), "image/jpeg");
+ if ( mDumpDepth ) {
+ saveToFile(getJpegData(mBayerImage), "bayer", "jpg");
+ }
} else {
mClearSightImage = (Image)msg.obj;
mEncodeResults |= MASK_CS_ENCODE;
+
}
} else if (msg.what == MSG_NEW_CAPTURE_RESULT) {
Log.d(TAG, "processNewEncodeEvent - newResult: " + msg.arg1);
@@ -1152,63 +1219,69 @@ public class ClearSightImageProcessor {
}
}
- private void saveMpoImage() {
- if(!mReadyToSave || mEncodeRequest != mEncodeResults) {
- Log.d(TAG, "saveMpoImage - not yet ready to save");
+ private void processNewGDepth(Message msg) {
+ mDepthMap = (GDepth.DepthMap)msg.obj;
+ mDepthMapReady = true;
+ }
+
+ private void saveClearSightImage() {
+ if ( !isReadyToSave() || mEncodeRequest != mEncodeResults) {
+ Log.d(TAG, "saveClearSightImage - not yet ready to save");
return;
}
- Log.d(TAG, "saveMpoImage");
if(mHasFailure) {
// don't save anything and fail
- Log.d(TAG, "saveMpoImage has failure - aborting.");
+ Log.d(TAG, "saveClearSightImage has failure - aborting.");
if(mCallback != null) mCallback.onClearSightFailure(null);
resetParams();
return;
}
+ Log.d(TAG, "saveClearSightImage");
+ byte[] clearSightBytes = getJpegData(mClearSightImage);
+
String title = (mNamedEntity == null) ? null : mNamedEntity.title;
long date = (mNamedEntity == null) ? -1 : mNamedEntity.date;
- int width = mBayerImage.getWidth();
- int height = mBayerImage.getHeight();
- if(mClearSightImage != null) {
+ int width = 0;
+ int height = 0;
+ if ( mBayerImage != null ) {
+ mBayerImage.getWidth();
+ mBayerImage.getHeight();
+ }
+ if ( mClearSightImage != null ) {
width = mClearSightImage.getWidth();
height = mClearSightImage.getHeight();
}
- byte[] clearSightBytes = getJpegData(mClearSightImage);
byte[] bayerBytes = getJpegData(mBayerImage);
- byte[] monoBytes = getJpegData(mMonoImage);
- ExifInterface exif = Exif.getExif(bayerBytes);
- int orientation = Exif.getOrientation(exif);
-
- if(clearSightBytes != null) {
- if(mCallback != null) mCallback.onClearSightSuccess(clearSightBytes);
- } else if (bayerBytes != null) {
- if(mCallback != null) mCallback.onClearSightFailure(bayerBytes);
- } else {
- if(mCallback != null) mCallback.onClearSightFailure(null);
- }
+ if ( bayerBytes != null ) {
+ ExifInterface exif = Exif.getExif(bayerBytes);
+ int orientation = Exif.getOrientation(exif);
+
+ if(clearSightBytes != null) {
+ if(mCallback != null) mCallback.onClearSightSuccess(clearSightBytes);
+ } else if (bayerBytes != null) {
+ if(mCallback != null) mCallback.onClearSightFailure(bayerBytes);
+ } else {
+ if(mCallback != null) mCallback.onClearSightFailure(null);
+ }
- if(monoBytes == null) {
- mMediaSaveService.addImage(
- clearSightBytes!=null?clearSightBytes:bayerBytes, title, date, null,
+ mMediaSaveService.addClearsightImage(
+ clearSightBytes != null ? clearSightBytes : bayerBytes,
+ mGImage, mDepthMap,title, date, null,
width, height, orientation, exif,
mMediaSavedListener,
mMediaSaveService.getContentResolver(), "jpeg");
- } else if (bayerBytes != null) {
- mMediaSaveService.addMpoImage(
- clearSightBytes,
- bayerBytes,
- monoBytes, width, height, title,
- date, null, orientation, mMediaSavedListener,
- mMediaSaveService.getContentResolver(), "jpeg");
}
-
resetParams();
}
+ private boolean isReadyToSave() {
+ return (mDepthMapReady &&mClearSightReady);
+ }
+
void resetParams() {
if(mBayerImage != null) {
mBayerImage.close();
@@ -1223,10 +1296,182 @@ public class ClearSightImageProcessor {
mClearSightImage = null;
}
mNamedEntity = null;
- mReadyToSave = false;
mHasFailure = false;
mEncodeRequest = 0;
mEncodeResults = 0;
+ mGImage = null;
+ mDepthMapReady = false;
+ mClearSightReady = false;
+ }
+ }
+
+ private class DepthProcessHandler extends Handler{
+ private TotalCaptureResult mReprocessCaptureResult;
+ private DDMNativeEngine mDDMNativeEngine;
+ public DepthProcessHandler(Looper looper) {
+ super(looper);
+ mDDMNativeEngine = new DDMNativeEngine();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch( msg.what ) {
+ case MSG_CALIBRATION_DATA:
+ setCalibrationdata(msg);
+ break;
+
+ case MSG_NEW_LENS_FOCUS_DISTANCE_BAYER:
+ setBayerLensFocusDistance(msg);
+ break;
+
+ case MSG_START_CAPTURE:
+ resetParams();
+ break;
+
+ case MSG_NEW_IMG:
+ registerImage(msg);
+ break;
+
+ case MSG_NEW_REPROC_RESULT:
+ registerReprocessResult(msg);
+ break;
+ }
+ }
+
+ private void setCalibrationdata(Message msg) {
+ mDDMNativeEngine.setCamSystemCalibrationData((CamSystemCalibrationData)msg.obj);
+ }
+ private void resetParams(){
+ Log.d(TAG, "resetParams");
+ mDDMNativeEngine.reset();
+ }
+
+ private void setBayerLensFocusDistance(Message msg) {
+ mDDMNativeEngine.setBayerLensFocusDistance((float)msg.obj);
+ }
+
+ private void registerImage(Message msg) {
+ boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER);
+ Image image = (Image) msg.obj;
+ if ( isBayer ) {
+ mDDMNativeEngine.setBayerImage(image);
+ }else{
+ mDDMNativeEngine.setMonoImage(image);
+ }
+
+ if ( mDDMNativeEngine.isReadyForGenerateDepth() ) {
+ generateDepthmap();
+ }
+ }
+
+ private void registerReprocessResult(Message msg) {
+
+ boolean isBayer = (msg.arg1 == CAM_TYPE_BAYER);
+ Log.d(TAG, "registerReprocessResult bayer=" + isBayer);
+ TotalCaptureResult result = (TotalCaptureResult)msg.obj;
+ if ( isBayer ) {
+ mDDMNativeEngine.setBayerReprocessResult(result);
+ }else{
+ mDDMNativeEngine.setMonoReprocessResult(result);
+ }
+
+ if ( mDDMNativeEngine.isReadyForGenerateDepth() ) {
+ generateDepthmap();
+ }
+
+ }
+
+ private void generateDepthmap() {
+ GDepth.DepthMap depthMap = null;
+ int[] size = new int[2];
+ if ( mDDMNativeEngine.getDepthMapSize(size) ) {
+ int width = size[0];
+ int height = size[1];
+ Bitmap bmp = Bitmap.createBitmap(width, height,
+ Bitmap.Config.ALPHA_8);
+ int stride = bmp.getRowBytes();
+ byte[] depthBuffer = new byte[stride*height];
+ Log.d(TAG, "depthMapWidth=" + width + " depthMapHeight="
+ + height + " stride=" + stride);
+ Rect roiRect = new Rect();
+
+ if ( mDDMNativeEngine.dualCameraGenerateDDM(depthBuffer, stride, roiRect) ) {
+ if ( mDumpDepth ) {
+ saveAsRGB(depthBuffer, width, height);
+ }
+ depthMap = new GDepth.DepthMap(width, height);
+ depthMap.roi = roiRect;
+ depthMap.rawDepth = depthBuffer;
+ }else{
+ Log.e(TAG, "dualCameraGenerateDDM failure");
+ }
+ }else{
+ Log.e(TAG, "getDepthMapSize failure");
+ }
+ if ( mDumpDepth ) {
+ dumpCameraParam();
+ }
+ mImageEncodeHandler.obtainMessage(MSG_NEW_DEPTH, 0, 0, depthMap).sendToTarget();
+ }
+
+ private void dumpCameraParam() {
+ saveToFile(mDDMNativeEngine.getOTPCalibration().getBytes(), "OTPdata", "txt");
+ saveToFile(mDDMNativeEngine.getBayerScaleCrop().getBytes(), "BayerScaleCrop", "txt");
+ saveToFile(mDDMNativeEngine.getMonoScaleCrop().getBytes(), "MonoScaleCrop", "txt");
+ }
+ }
+
+ private void saveAsRGB(byte[] depth, int width, int height) {
+ int[] colors = new int[depth.length];
+ for(int i=0; i < colors.length; ++i) {
+ colors[i] = (256+depth[i])%256;
+ }
+
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ for( int y=0; y < height; ++y ) {
+ for( int x=0; x < width; ++x) {
+ int c = colors[y*width+x];
+ bitmap.setPixel(x, y, Color.rgb(c, c, c));
+ }
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
+ File file = new File("sdcard/depthmap_rgb.jpg");
+ byte[] jpeg = baos.toByteArray();
+ Log.d(TAG, "jpeg.size=" + jpeg.length);
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ out.write(jpeg, 0, jpeg.length);
+ }catch(Exception e) {
+ Log.d(TAG, e.toString());
+ }finally {
+ if (out != null) {
+ try {
+ out.close();
+ }catch(Exception e){
+ Log.d(TAG, e.toString());
+ }
+ }
+ }
+ }
+
+ private void saveToFile(byte[] bytes, String name, String format){
+ File file = new File("sdcard/"+ name + "." + format);
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ out.write(bytes, 0, bytes.length);
+ }catch(Exception e) {
+ Log.d(TAG, e.toString());
+ }finally {
+ if (out != null) {
+ try {
+ out.close();
+ }catch(Exception e){
+ Log.d(TAG, e.toString());
+ }
+ }
}
}
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java b/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java
index 402ffce84..8b30ca032 100644
--- a/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightNativeEngine.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 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
@@ -412,7 +412,7 @@ public class ClearSightNativeEngine {
public static class CamSystemCalibrationData {
private static final String[] CALIB_FMT_STRINGS = {
- "Calibration OTP format version = %x\n",
+ "Calibration OTP format version = %d\n",
"Main Native Sensor Resolution width = %dpx\n",
"Main Native Sensor Resolution height = %dpx\n",
"Main Calibration Resolution width = %dpx\n",
diff --git a/src/org/codeaurora/snapcam/filter/DDMNativeEngine.java b/src/org/codeaurora/snapcam/filter/DDMNativeEngine.java
new file mode 100644
index 000000000..b2b0a523d
--- /dev/null
+++ b/src/org/codeaurora/snapcam/filter/DDMNativeEngine.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2017, 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 org.codeaurora.snapcam.filter;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import android.graphics.Rect;
+import android.media.Image;
+import android.media.Image.Plane;
+import android.util.Log;
+
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.TotalCaptureResult;
+
+import org.codeaurora.snapcam.filter.ClearSightNativeEngine.CamSystemCalibrationData;
+
+public class DDMNativeEngine {
+ private static final String TAG = "DDMNativeEngine";
+ static {
+ try {//load jni_dualcamera
+ System.loadLibrary("jni_dualcamera");
+ mLibLoaded = true;
+ Log.v(TAG, "successfully loaded jni_dualcamera lib");
+ } catch (UnsatisfiedLinkError e) {
+ Log.e(TAG, "failed to load jni_dualcamera lib");
+ Log.e(TAG, e.toString());
+ e.printStackTrace();
+ mLibLoaded = false;
+ }
+
+ }
+
+ private CaptureResult.Key<byte[]> SCALE_CROP_ROTATION_REPROCESS_BLOB =
+ new CaptureResult.Key<byte[]>(
+ "org.codeaurora.qcamera3.hal_private_data.reprocess_data_blob",
+ byte[].class);
+
+ private static boolean mLibLoaded;
+ private Image mBayerImage;
+ private Image mMonoImage;
+ private ByteBuffer mPrimaryY;
+ private ByteBuffer mPrivaryVU;
+ CamReprocessInfo mBayerCamReprocessInfo;
+ CamReprocessInfo mMonoCamReprocessInfo;
+ CamSystemCalibrationData mCamSystemCalibrationData;
+ private float mLensFocusDistance;
+ private static final int Y_PLANE = 0;
+ private static final int VU_PLANE = 2;
+
+ public boolean getDepthMapSize(int[] depthMap){
+ return nativeGetDepthMapSize(mBayerImage.getWidth(), mBayerImage.getHeight(), depthMap);
+ }
+
+ public void setCamSystemCalibrationData(CamSystemCalibrationData otpCalibration){
+ mCamSystemCalibrationData = otpCalibration;
+ }
+
+ public String getOTPCalibration() {
+ return mCamSystemCalibrationData.toString();
+ }
+
+ public void reset() {
+ mBayerImage = null;
+ mMonoImage = null;
+ mBayerCamReprocessInfo = null;
+ mMonoCamReprocessInfo = null;
+ mLensFocusDistance = 0;
+ }
+ public boolean isReadyForGenerateDepth(){
+ return mBayerImage != null && mMonoImage != null
+ && mBayerCamReprocessInfo != null && mMonoCamReprocessInfo != null;
+ }
+
+ public void setBayerLensFocusDistance(float lensFocusDistance) {
+ mLensFocusDistance = lensFocusDistance;
+ }
+ public void setBayerImage(Image image){
+ mBayerImage = image;
+ }
+
+ public void setMonoImage(Image image) {
+ mMonoImage = image;
+ }
+
+ public void setBayerReprocessResult(CaptureResult result ){
+ byte[] bytes = result.get(SCALE_CROP_ROTATION_REPROCESS_BLOB);
+ mBayerCamReprocessInfo = CamReprocessInfo.createCamReprocessFromBytes(bytes);
+ }
+
+ public String getBayerScaleCrop() {
+ return mBayerCamReprocessInfo.toString();
+ }
+
+ public void setMonoReprocessResult(CaptureResult result) {
+ byte[] bytes = result.get(SCALE_CROP_ROTATION_REPROCESS_BLOB);
+ mMonoCamReprocessInfo = CamReprocessInfo.createCamReprocessFromBytes(bytes);
+ }
+
+ public String getMonoScaleCrop(){
+ return mMonoCamReprocessInfo.toString();
+ }
+
+ public boolean dualCameraGenerateDDM(byte[] depthMapBuffer, int depthMapStride, Rect roiRect) {
+ if ( mLensFocusDistance == 0 ){
+ Log.e(TAG, " dualCameraGenerateDDM error: mLensFocusDistance is 0");
+ return false;
+ }
+
+ if (mBayerImage == null || mMonoImage == null ) {
+ Log.e(TAG, "mBayerImage=" +(mBayerImage == null)+ " mMonoImage=" + (mMonoImage == null));
+ return false;
+ }
+
+ if ( depthMapBuffer == null ) {
+ Log.e(TAG, "depthMapBuffer can't be null");
+ return false;
+ }
+
+ if ( mMonoCamReprocessInfo== null
+ || mBayerCamReprocessInfo == null
+ || mCamSystemCalibrationData == null ) {
+ Log.e(TAG, "mMonoCamReprocessInfo== null:" +(mMonoCamReprocessInfo== null)
+ + " mBayerCamReprocessInfo == null:" +(mBayerCamReprocessInfo == null)
+ + " mCamSystemCalibrationData == null:" +(mCamSystemCalibrationData == null));
+ return false;
+ }
+
+ Plane[] bayerPlanes = mBayerImage.getPlanes();
+ Plane[] monoPlanes = mMonoImage.getPlanes();
+ int[] goodRoi = new int[4];
+ boolean result = nativeDualCameraGenerateDDM(
+ bayerPlanes[Y_PLANE].getBuffer(),
+ bayerPlanes[VU_PLANE].getBuffer(),
+ mBayerImage.getWidth(),
+ mBayerImage.getHeight(),
+ bayerPlanes[Y_PLANE].getRowStride(),
+ bayerPlanes[VU_PLANE].getRowStride(),
+
+ monoPlanes[Y_PLANE].getBuffer(),
+ monoPlanes[VU_PLANE].getBuffer(),
+ mMonoImage.getWidth(),
+ mMonoImage.getHeight(),
+ monoPlanes[Y_PLANE].getRowStride(),
+ monoPlanes[VU_PLANE].getRowStride(),
+
+ depthMapBuffer,
+ depthMapStride,
+
+ goodRoi,
+
+ mBayerCamReprocessInfo.toString(),
+ mMonoCamReprocessInfo.toString(),
+ mCamSystemCalibrationData.toString(),
+ mLensFocusDistance,
+ true);
+ roiRect.left = goodRoi[0];
+ roiRect.top = goodRoi[1];
+ roiRect.right = goodRoi[0] + goodRoi[2];
+ roiRect.bottom = goodRoi[1] + goodRoi[3];
+
+ return result;
+ }
+
+
+
+ private native boolean nativeGetDepthMapSize(int primaryWidth, int primaryHeight,int[] size);
+
+ private native boolean nativeDualCameraGenerateDDM(
+ ByteBuffer primaryY,
+ ByteBuffer primaryVU,
+ int primaryWidth,
+ int primaryHeight,
+ int primaryStrideY,
+ int primaryStrideVU,
+
+ ByteBuffer auxiliaryY,
+ ByteBuffer auxiliaryVU,
+ int auxiliaryWidth,
+ int auxiliaryHeight,
+ int auxiliaryStrideY,
+ int auxiliaryStrideVU,
+
+ byte[] outDst,
+ int dstStride,
+
+ int[] roiRect,
+
+ String scaleCropRotationDataPrimaryCamera,
+ String scaleCropRotationDataAuxiliaryCamera,
+ String otpCalibration,
+ float focalLengthPrimaryCamera,
+ boolean isAuxiliaryMonoSensor);
+
+ public static class DepthMap{
+ private int width;
+ private int height;
+ private ByteBuffer buffer;
+ private int stride;
+ private Rect roi;
+ }
+ public static class CamStreamCropInfo{
+ int stream_id;
+ Rect crop;
+ Rect roi_map;
+
+ private CamStreamCropInfo(){}
+
+ public static CamStreamCropInfo createFromBytes(byte[] bytes) {
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+ return createFromByteBuffer(buffer);
+ }
+
+ public static CamStreamCropInfo createFromByteBuffer(ByteBuffer buffer) {
+ CamStreamCropInfo camStreamCropInfo = new CamStreamCropInfo();
+ camStreamCropInfo.stream_id = buffer.getInt();
+ Rect crop = new Rect();
+ crop.left = buffer.getInt();
+ crop.top = buffer.getInt();
+ crop.right = crop.left + buffer.getInt();
+ crop.bottom = crop.top + buffer.getInt();
+ camStreamCropInfo.crop = crop;
+
+ Rect roi_map = new Rect();
+ roi_map.left = buffer.getInt();
+ roi_map.top = buffer.getInt();
+ roi_map.right = roi_map.left + buffer.getInt();
+ roi_map.bottom = roi_map.top + buffer.getInt();
+ camStreamCropInfo.roi_map = roi_map;
+
+ return camStreamCropInfo;
+ }
+ }
+
+ public static class CamRotationInfo {
+ int jpeg_rotation;
+ int device_rotation;
+ int stream_id;
+ private CamRotationInfo(){}
+
+ public static CamRotationInfo createCamReprocessFromBytes(byte[] bytes) {
+ ByteBuffer buf = ByteBuffer.wrap(bytes);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ return createFromByteBuffer(buf);
+ }
+ public static CamRotationInfo createFromByteBuffer(ByteBuffer buffer) {
+ CamRotationInfo rotation_info = new CamRotationInfo();
+ rotation_info.jpeg_rotation = buffer.getInt();
+ rotation_info.device_rotation = buffer.getInt();
+ rotation_info.stream_id = buffer.getInt();
+ return rotation_info;
+ }
+ }
+ public static class CamReprocessInfo{
+ CamStreamCropInfo sensor_crop_info;
+ CamStreamCropInfo camif_crop_info;
+ CamStreamCropInfo isp_crop_info;
+ CamStreamCropInfo cpp_crop_info;
+ float af_focal_length_ratio;
+ int pipeline_flip;
+ CamRotationInfo rotation_info;
+
+ private final String SCALE_CROP_ROTATION_FORMAT_STRING[] = {
+ "Sensor Crop left = %d\n",
+ "Sensor Crop top = %d\n",
+ "Sensor Crop width = %d\n",
+ "Sensor Crop height = %d\n",
+ "Sensor ROI Map left = %d\n",
+ "Sensor ROI Map top = %d\n",
+ "Sensor ROI Map width = %d\n",
+ "Sensor ROI Map height = %d\n",
+ "CAMIF Crop left = %d\n",
+ "CAMIF Crop top = %d\n",
+ "CAMIF Crop width = %d\n",
+ "CAMIF Crop height = %d\n",
+ "CAMIF ROI Map left = %d\n",
+ "CAMIF ROI Map top = %d\n",
+ "CAMIF ROI Map width = %d\n",
+ "CAMIF ROI Map height = %d\n",
+ "ISP Crop left = %d\n",
+ "ISP Crop top = %d\n",
+ "ISP Crop width = %d\n",
+ "ISP Crop height = %d\n",
+ "ISP ROI Map left = %d\n",
+ "ISP ROI Map top = %d\n",
+ "ISP ROI Map width = %d\n",
+ "ISP ROI Map height = %d\n",
+ "CPP Crop left = %d\n",
+ "CPP Crop top = %d\n",
+ "CPP Crop width = %d\n",
+ "CPP Crop height = %d\n",
+ "CPP ROI Map left = %d\n",
+ "CPP ROI Map top = %d\n",
+ "CPP ROI Map width = %d\n",
+ "CPP ROI Map height = %d\n",
+ "Focal length Ratio = %f\n",
+ "Current pipeline mirror flip setting = %d\n",
+ "Current pipeline rotation setting = %d\n"
+ };
+
+ public static CamReprocessInfo createCamReprocessFromBytes(byte[] bytes){
+ ByteBuffer buf = ByteBuffer.wrap(bytes);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ return createCamReprocessFromBytes(buf);
+ }
+ public static CamReprocessInfo createCamReprocessFromBytes(ByteBuffer buffer){
+ CamReprocessInfo scaleCropRotation = new CamReprocessInfo();
+ scaleCropRotation.sensor_crop_info = CamStreamCropInfo.createFromByteBuffer(buffer);
+ scaleCropRotation.camif_crop_info = CamStreamCropInfo.createFromByteBuffer(buffer);
+ scaleCropRotation.isp_crop_info = CamStreamCropInfo.createFromByteBuffer(buffer);
+ scaleCropRotation.cpp_crop_info = CamStreamCropInfo.createFromByteBuffer(buffer);
+ scaleCropRotation.af_focal_length_ratio = buffer.getFloat();
+ scaleCropRotation.pipeline_flip = buffer.getInt();
+ scaleCropRotation.rotation_info = CamRotationInfo.createFromByteBuffer(buffer);
+ return scaleCropRotation;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[0], this.sensor_crop_info.crop.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[1], this.sensor_crop_info.crop.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[2], this.sensor_crop_info.crop.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[3], this.sensor_crop_info.crop.height()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[4], this.sensor_crop_info.roi_map.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[5], this.sensor_crop_info.roi_map.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[6], this.sensor_crop_info.roi_map.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[7], this.sensor_crop_info.roi_map.height()));
+
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[8], this.camif_crop_info.crop.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[9], this.camif_crop_info.crop.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[10], this.camif_crop_info.crop.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[11], this.camif_crop_info.crop.height()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[12], this.camif_crop_info.roi_map.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[13], this.camif_crop_info.roi_map.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[14], this.camif_crop_info.roi_map.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[15], this.camif_crop_info.roi_map.height()));
+
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[16], this.isp_crop_info.crop.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[17], this.isp_crop_info.crop.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[18], this.isp_crop_info.crop.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[19], this.isp_crop_info.crop.height()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[20], this.isp_crop_info.roi_map.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[21], this.isp_crop_info.roi_map.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[22], this.isp_crop_info.roi_map.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[23], this.isp_crop_info.roi_map.height()));
+
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[24], this.cpp_crop_info.crop.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[25], this.cpp_crop_info.crop.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[26], this.cpp_crop_info.crop.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[27], this.cpp_crop_info.crop.height()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[28], this.cpp_crop_info.roi_map.left));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[29], this.cpp_crop_info.roi_map.top));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[30], this.cpp_crop_info.roi_map.width()));
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[31], this.cpp_crop_info.roi_map.height()));
+
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[32], this.af_focal_length_ratio));
+
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[33], this.pipeline_flip));
+
+ sb.append(String.format(SCALE_CROP_ROTATION_FORMAT_STRING[34], this.rotation_info.jpeg_rotation));
+ return sb.toString();
+ }
+
+ }
+
+
+} \ No newline at end of file
diff --git a/src/org/codeaurora/snapcam/filter/GDepth.java b/src/org/codeaurora/snapcam/filter/GDepth.java
new file mode 100644
index 000000000..8f9a935a9
--- /dev/null
+++ b/src/org/codeaurora/snapcam/filter/GDepth.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2017, 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 org.codeaurora.snapcam.filter;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Rect;
+import android.hardware.Camera.Size;
+import android.util.Base64;
+import android.util.Log;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+
+import java.io.OutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.BufferedOutputStream;
+
+import com.adobe.xmp.XMPException;
+import com.adobe.xmp.XMPMeta;
+import com.adobe.xmp.XMPMetaFactory;
+
+public class GDepth{
+ private final static String TAG = "Flow_GDepth";
+ public final static String NAMESPACE_URL = "http://ns.google.com/photos/1.0/depthmap/";
+ public final static String PREFIX = "GDepth";
+ public final static String PROPERTY_FORMAT = "Format";
+ public final static String PROPERTY_NEAR = "Near";
+ public final static String PROPERTY_FAR = "Far";
+ public final static String PROPERTY_MIME = "Mime";
+ public final static String PROPERTY_DATA = "Data";
+ //extend roi
+ public final static String PROPERTY_ROI_X = "RoiX";
+ public final static String PROPERTY_ROI_Y = "RoiY";
+ public final static String PROPERTY_ROI_WIDTH = "RoiWidth";
+ public final static String PROPERTY_ROI_HEIGHT = "RoiHeight";
+
+ public final static String FORMAT_RANGE_INVERSE="RangeInverse";
+ public final static String FORMAT_RANGLE_LINEAR = "RangeLinear";
+ private final static String MIME = "image/jpeg";
+
+ private DepthMap mDepthMap;
+ private String mData;
+ private int mNear;
+ private int mFar;
+ private final String mFormat = "RangeLinear";
+ private int[] mMap;
+
+ static {
+ try {
+ XMPMetaFactory.getSchemaRegistry().registerNamespace(
+ NAMESPACE_URL, PREFIX);
+ } catch (XMPException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private GDepth(DepthMap depthMap){
+ mDepthMap = depthMap;
+ mMap = new int[depthMap.buffer.length];
+
+ for( int i=0; i < mMap.length; ++i ) {
+ mMap[i] = (256+depthMap.buffer[i])%256;
+ }
+ mNear = mFar = mMap[0];
+ for(int d : mMap ) {
+ if ( d < mNear) {
+ mNear = d;
+ }else if ( d > mFar) {
+ mFar = d;
+ }
+ }
+ }
+
+ public int getNear() {
+ return mNear;
+ }
+
+ public int getFar(){
+ return mFar;
+ }
+
+ public String getFormat(){
+ return mFormat;
+ }
+
+ public String getMime() {
+ return MIME;
+ }
+
+ public String getData(){
+ return mData;
+ }
+
+ public Rect getRoi() {
+ return mDepthMap.roi;
+ }
+ public static GDepth createGDepth(DepthMap depthMap){
+ GDepth gDepth = new GDepth(depthMap);
+ if ( gDepth.encoding() ) {
+ return gDepth;
+ }
+ return null;
+ }
+
+ private boolean encoding(){
+ Log.d(TAG, "encoding");
+ boolean result = false;
+ int[] grayscaleImage = convertIntoImage(mMap);
+ byte[] jpegBytes = compressToJPEG(grayscaleImage );
+ if (jpegBytes != null ) {
+ String base64String = serializeAsBase64Str(jpegBytes);
+ result = true;
+ mData = base64String;
+ }else{
+ Log.e(TAG, "compressToJPEG failure");
+ }
+
+ return result;
+ }
+
+ private int[] convertIntoImage(int[] depthMap) {
+ int[] imageBuffer = new int[depthMap.length];
+ float dividend = mFar-mNear;
+ for ( int i =0; i < imageBuffer.length; ++i) {
+ if ( depthMap[i] == 0 && mNear == 0 ) {
+ imageBuffer[i] = 0;
+ }else{
+ imageBuffer[i] = getRangeLinearDepth(depthMap[i], mNear, dividend);
+ }
+ }
+ return imageBuffer;
+ }
+
+ private int getRangeLinearDepth(int depth, int near, float dividend) {
+ return (int)(255*(depth-near)/dividend);
+ }
+
+ private int getRangeLinearDepth(int depth, int near, int far) {
+ return (int)(255*(depth-near)/(float)(far-near));
+ }
+
+ private byte[] compressToJPEG(int[] image) {
+ Log.d(TAG, "compressToJPEG int[].size=" + image.length);
+ byte[] bitsBuffer = new byte[image.length];
+ for(int i=0; i < image.length; ++i){
+ bitsBuffer[i] = (byte)image[i];
+ }
+ return compressToJPEG(bitsBuffer);
+ }
+
+ private byte[] compressToJPEG(byte[] image) {
+ Log.d(TAG, "compressToJPEG byte[].size=" + image.length);
+ Bitmap bmp = BitmapFactory.decodeByteArray (image, 0, image.length);
+ if ( bmp == null ) {
+ Log.d(TAG, " buffer can't be decoded ");
+ return null;
+ }
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ bmp.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
+ return outputStream.toByteArray();
+ }
+
+ private String serializeAsBase64Str(byte[] image) {
+ Log.d(TAG, "serializeAsBase64Str");
+ return Base64.encodeToString(image, Base64.DEFAULT);
+ }
+
+ private void saveAsFile(String str, String name){
+ Log.d(TAG, "saveAsFile " + "sdcard/DDM/"+ TAG + name + ".log");
+ File file = new File("sdcard/DDM/"+ TAG + name + ".log");
+
+ OutputStream out = null;
+ byte[] bytes = str.getBytes();
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ out.write(bytes, 0, bytes.length);
+ }catch(Exception e) {
+ Log.d(TAG, e.toString());
+ }finally {
+ if (out != null) {
+ try {
+ out.close();
+ }catch(Exception e){
+ Log.d(TAG, e.toString());
+ }
+ }
+ }
+ }
+
+ private void saveAsJPEG(byte[] bytes){
+ Log.d(TAG, "saveAsJPEG");
+ File file = new File("sdcard/"+ System.currentTimeMillis() + "_depth.JPEG");
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ out.write(bytes, 0, bytes.length);
+ }catch(Exception e) {
+ Log.d(TAG, e.toString());
+ }finally {
+ if (out != null) {
+ try {
+ out.close();
+ }catch(Exception e){
+ Log.d(TAG, e.toString());
+ }
+ }
+ }
+ }
+
+ public static class DepthMap{
+ public byte[] buffer;
+ public int width;
+ public int height;
+ public Rect roi;
+ public byte[] rawDepth;
+ public DepthMap(int width, int height){
+ this.width = width;
+ this.height = height;
+ }
+ }
+
+
+ private GDepth(int near, int far, String data) {
+ this.mNear = near;
+ this.mFar = far;
+ this.mData = data;
+ }
+ public static GDepth createGDepth(XMPMeta xmpMeta){
+ try {
+ int near = Integer.parseInt((String)
+ xmpMeta.getProperty(GDepth.NAMESPACE_URL, PROPERTY_NEAR).getValue());
+ int far = Integer.parseInt((String)
+ xmpMeta.getProperty(GDepth.NAMESPACE_URL, PROPERTY_FAR).getValue());
+ String data = (String)xmpMeta.getProperty(
+ GDepth.NAMESPACE_URL, PROPERTY_DATA).getValue();
+ String format = (String)xmpMeta.getProperty(
+ GDepth.NAMESPACE_URL, PROPERTY_FORMAT).getValue();
+ Log.d(TAG, "new GDepth: nerar=" + near+ " far=" + far + "format=" + format+ " data=" + data);
+ int x = Integer.parseInt((String)
+ xmpMeta.getProperty(GDepth.NAMESPACE_URL, PROPERTY_ROI_X).getValue());
+ int y = Integer.parseInt((String)
+ xmpMeta.getProperty(GDepth.NAMESPACE_URL, PROPERTY_ROI_Y).getValue());
+ int width = Integer.parseInt((String)
+ xmpMeta.getProperty(GDepth.NAMESPACE_URL, PROPERTY_ROI_WIDTH).getValue());
+ int height = Integer.parseInt((String)
+ xmpMeta.getProperty(GDepth.NAMESPACE_URL, PROPERTY_ROI_HEIGHT).getValue());
+ Log.d(TAG, "x=" + x + " y=" + y + " width=" + width + " height=" + height);
+ GDepth gDepth = new GDepth(near, far, data);
+ return gDepth;
+ }catch(XMPException e){
+ Log.e(TAG, e.toString());
+ }catch(Exception e) {
+ Log.e(TAG, e.toString());
+ }
+ return null;
+ }
+
+ public boolean decode() {
+ Log.d(TAG, "decode");
+ byte[] depthBuffer = Base64.decode(mData, Base64.DEFAULT);
+ saveAsJPEG(depthBuffer);
+ //TODO:
+ //convert JPEG compress bytes to bytes
+
+ int[] intDepthBuffer = new int[depthBuffer.length];
+ int[] intDepth = new int[depthBuffer.length];
+
+ //conver to 0-255;
+ for( int i=0; i < intDepthBuffer.length; ++i) {
+ intDepthBuffer[i] = (256+depthBuffer[i])%256;
+ }
+ //conver to depth value
+
+ return false;
+
+ }
+} \ No newline at end of file
diff --git a/src/org/codeaurora/snapcam/filter/GImage.java b/src/org/codeaurora/snapcam/filter/GImage.java
new file mode 100644
index 000000000..bac6fd296
--- /dev/null
+++ b/src/org/codeaurora/snapcam/filter/GImage.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 org.codeaurora.snapcam.filter;
+
+import com.adobe.xmp.XMPException;
+import com.adobe.xmp.XMPMeta;
+import com.adobe.xmp.XMPMetaFactory;
+
+import android.util.Base64;
+
+public class GImage{
+ public final static String NAMESPACE_URL = "http://ns.google.com/photos/1.0/image/";
+ public final static String PREFIX = "GImage";
+ public final static String PROPERTY_MIME = "Mime";
+ public final static String PROPERTY_DATA = "Data";
+
+ static {
+ try {
+ XMPMetaFactory.getSchemaRegistry().registerNamespace(
+ NAMESPACE_URL, PREFIX);
+ } catch (XMPException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String mMime = "image/jpeg";
+ private String mData;
+
+ public GImage(byte[] data, String mime){
+ mData = Base64.encodeToString(data, Base64.DEFAULT);
+ mMime = mime;
+ }
+
+ public String getMime(){
+ return mMime;
+ }
+
+ public String getData(){
+ return mData;
+ }
+} \ No newline at end of file