summaryrefslogtreecommitdiffstats
path: root/src/org/codeaurora/snapcam
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/codeaurora/snapcam')
-rw-r--r--src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java125
1 files changed, 114 insertions, 11 deletions
diff --git a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
index ea37d379d..0633b0c56 100644
--- a/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
+++ b/src/org/codeaurora/snapcam/filter/ClearSightImageProcessor.java
@@ -34,6 +34,7 @@ import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.codeaurora.snapcam.filter.ClearSightNativeEngine.CamSystemCalibrationData;
@@ -53,6 +54,7 @@ import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.InputConfiguration;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.Image.Plane;
import android.media.ImageReader;
@@ -65,6 +67,7 @@ import android.os.Message;
import android.os.SystemProperties;
import android.util.Log;
import android.util.SparseLongArray;
+import android.util.Size;
import android.view.Surface;
import com.android.camera.CaptureModule;
@@ -75,6 +78,7 @@ import com.android.camera.MediaSaveService.OnMediaSavedListener;
import com.android.camera.PhotoModule.NamedImages;
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";
@@ -86,6 +90,13 @@ public class ClearSightImageProcessor {
private static final long DEFAULT_TIMESTAMP_THRESHOLD_MS = 10;
private static final int DEFAULT_IMAGES_TO_BURST = 4;
+ private static final long MIN_MONO_AREA = 1900000; // ~1.9 MP
+ private static final Size[] MONO_SIZES = {
+ new Size(1600, 1200), // 4:3
+ new Size(1920, 1080), // 16:9
+ new Size(1400, 1400) // 1:1
+ };
+
private static final int MSG_START_CAPTURE = 0;
private static final int MSG_NEW_IMG = 1;
private static final int MSG_NEW_CAPTURE_RESULT = 2;
@@ -107,6 +118,9 @@ public class ClearSightImageProcessor {
private ImageReader[] mImageReader = new ImageReader[NUM_CAM];
private ImageReader[] mEncodeImageReader = new ImageReader[NUM_CAM];
private ImageWriter[] mImageWriter = new ImageWriter[NUM_CAM];
+ private float mFinalPictureRatio;
+ private Size mFinalPictureSize;
+ private Size mFinalMonoSize;
private ImageProcessHandler mImageProcessHandler;
private ClearsightRegisterHandler mClearsightRegisterHandler;
@@ -163,7 +177,8 @@ public class ClearSightImageProcessor {
return mInstance;
}
- public void init(int width, int height, Context context, OnMediaSavedListener mediaListener) {
+ public void init(StreamConfigurationMap map, int width, int height,
+ Context context, OnMediaSavedListener mediaListener) {
mImageProcessThread = new HandlerThread("CameraImageProcess");
mImageProcessThread.start();
mClearsightRegisterThread = new HandlerThread("ClearsightRegister");
@@ -178,10 +193,16 @@ public class ClearSightImageProcessor {
mClearsightProcessHandler = new ClearsightProcessHandler(mClearsightProcessThread.getLooper());
mImageEncodeHandler = new ImageEncodeHandler(mImageEncodeThread.getLooper());
- mImageReader[CAM_TYPE_BAYER] = createImageReader(CAM_TYPE_BAYER, width, height);
- mImageReader[CAM_TYPE_MONO] = createImageReader(CAM_TYPE_MONO, width, height);
- mEncodeImageReader[CAM_TYPE_BAYER] = createEncodeImageReader(CAM_TYPE_BAYER, width, height);
- mEncodeImageReader[CAM_TYPE_MONO] = createEncodeImageReader(CAM_TYPE_MONO, width, height);
+ mFinalPictureSize = new Size(width, height);
+ mFinalPictureRatio = (float)width / (float)height;
+ mFinalMonoSize = getFinalMonoSize();
+ Size maxSize = findMaxOutputSize(map);
+ int maxWidth = maxSize.getWidth();
+ int maxHeight = maxSize.getHeight();
+ mImageReader[CAM_TYPE_BAYER] = createImageReader(CAM_TYPE_BAYER, maxWidth, maxHeight);
+ mImageReader[CAM_TYPE_MONO] = createImageReader(CAM_TYPE_MONO, maxWidth, maxHeight);
+ mEncodeImageReader[CAM_TYPE_BAYER] = createEncodeImageReader(CAM_TYPE_BAYER, maxWidth, maxHeight);
+ mEncodeImageReader[CAM_TYPE_MONO] = createEncodeImageReader(CAM_TYPE_MONO, maxWidth, maxHeight);
mMediaSavedListener = mediaListener;
CameraManager cm = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
@@ -859,13 +880,26 @@ public class ClearSightImageProcessor {
private void sendReprocessRequest(CaptureRequest.Builder reprocRequest, Image image, final int camType) {
try {
+ reprocRequest.set(CaptureModule.JpegCropEnableKey, (byte)1);
+
Rect cropRect = image.getCropRect();
- if(cropRect != null &&
- !cropRect.isEmpty()) {
- // has crop rect. apply to jpeg request
- reprocRequest.set(CaptureModule.JpegCropEnableKey, (byte)1);
- reprocRequest.set(CaptureModule.JpegCropRectKey,
- new int[] {cropRect.left, cropRect.top, cropRect.width(), cropRect.height()});
+ if(cropRect == null ||
+ cropRect.isEmpty()) {
+ // if no crop rect set, init to default image width + height
+ cropRect = new Rect(0, 0, image.getWidth(), image.getHeight());
+ }
+
+ cropRect = getFinalCropRect(cropRect);
+ // has crop rect. apply to jpeg request
+ reprocRequest.set(CaptureModule.JpegCropRectKey,
+ new int[] {cropRect.left, cropRect.top, cropRect.width(), cropRect.height()});
+
+ if(camType == CAM_TYPE_MONO) {
+ reprocRequest.set(CaptureModule.JpegRoiRectKey,
+ new int[] {0, 0, mFinalMonoSize.getWidth(), mFinalMonoSize.getHeight()});
+ } else {
+ reprocRequest.set(CaptureModule.JpegRoiRectKey,
+ new int[] {0, 0, mFinalPictureSize.getWidth(), mFinalPictureSize.getHeight()});
}
mImageWriter[camType].queueInputImage(image);
@@ -1073,4 +1107,73 @@ public class ClearSightImageProcessor {
return data;
}
+
+ private Size findMaxOutputSize(StreamConfigurationMap map) {
+ Size[] sizes = map.getOutputSizes(ImageFormat.YUV_420_888);
+ Arrays.sort(sizes, new CameraUtil.CompareSizesByArea());
+ return sizes[sizes.length-1];
+ }
+
+ private Size getFinalMonoSize() {
+ Size finalSize = null;
+ long finalPicArea = mFinalPictureSize.getWidth() * mFinalPictureSize.getHeight();
+
+ // if final pic size is less than 2MP, then use same MONO size
+ if(finalPicArea > MIN_MONO_AREA) {
+ for(Size size:MONO_SIZES) {
+ float monoRatio = (float)size.getWidth() / (float)size.getHeight();
+ if(monoRatio == mFinalPictureRatio) {
+ finalSize = size;
+ break;
+ } else if (Math.abs(monoRatio - mFinalPictureRatio) < 0.1f) {
+ // close enough
+ int monoWidth = size.getWidth();
+ int monoHeight = size.getHeight();
+ if(monoRatio > mFinalPictureRatio) {
+ // keep width, increase height to match final ratio
+ // add .5 to round up if necessary
+ monoHeight = (int)(((float)monoWidth / mFinalPictureRatio) + .5f);
+ } else if(monoRatio < mFinalPictureRatio) {
+ // keep height, increase width to match final ratio
+ // add .5 to round up if necessary
+ monoWidth = (int)(((float)monoHeight * mFinalPictureRatio) + .5f);
+ }
+ finalSize = new Size(monoWidth, monoHeight);
+ }
+ }
+ }
+
+ if(finalSize == null) {
+ // set to mFinalPictureSize if matching size not found
+ // or if final resolution is less than 2 MP
+ finalSize = mFinalPictureSize;
+ }
+
+ return finalSize;
+ }
+
+ private Rect getFinalCropRect(Rect rect) {
+ Rect finalRect = new Rect(rect);
+ float rectRatio = (float) rect.width()/(float) rect.height();
+
+ // if ratios are different, adjust crop rect to fit ratio
+ // if ratios are same, no need to adjust crop
+ if(rectRatio > mFinalPictureRatio) {
+ // ratio indicates need for horizontal crop
+ // add .5 to round up if necessary
+ int newWidth = (int)(((float)rect.height() * mFinalPictureRatio) + .5f);
+ int newXoffset = (rect.width() - newWidth)/2;
+ finalRect.left = newXoffset;
+ finalRect.right = newXoffset + newWidth;
+ } else if(rectRatio < mFinalPictureRatio) {
+ // ratio indicates need for vertical crop
+ // add .5 to round up if necessary
+ int newHeight = (int)(((float)rect.width() / mFinalPictureRatio) + .5f);
+ int newYoffset = (rect.height() - newHeight)/2;
+ finalRect.top = newYoffset;
+ finalRect.bottom = newYoffset + newHeight;
+ }
+
+ return finalRect;
+ }
}