summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/imageprocessor
diff options
context:
space:
mode:
authorJack Yoo <jyoo@codeaurora.org>2016-09-29 12:35:56 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-10-13 15:57:04 -0700
commit392d833321dd0d05aeb80bd33240394ea9ea5591 (patch)
tree550ea80b0cc4099604133c50a4ede73829117b50 /src/com/android/camera/imageprocessor
parentaa24e964a6c6f7849ba843a37df1387c0894d725 (diff)
downloadandroid_packages_apps_Snap-392d833321dd0d05aeb80bd33240394ea9ea5591.tar.gz
android_packages_apps_Snap-392d833321dd0d05aeb80bd33240394ea9ea5591.tar.bz2
android_packages_apps_Snap-392d833321dd0d05aeb80bd33240394ea9ea5591.zip
SnapdragonCamera: frame capture path
Frame the path for each capture. 1. ZSL image -> YUV reprocess -> filters -> framework jpeg encoding 2. Non-ZSL -> filters -> framework jpeg encoding 3. Optimizing bestpicture filter image saving 4. Adjusting roi according to the mirror Change-Id: I8989ec57beec3420e6f4311dff951af0a84f5ba9 CRs-Fixed: 1071798
Diffstat (limited to 'src/com/android/camera/imageprocessor')
-rw-r--r--src/com/android/camera/imageprocessor/PostProcessor.java314
-rw-r--r--src/com/android/camera/imageprocessor/filter/BestpictureFilter.java163
-rw-r--r--src/com/android/camera/imageprocessor/filter/ChromaflashFilter.java13
-rw-r--r--src/com/android/camera/imageprocessor/filter/UbifocusFilter.java14
4 files changed, 342 insertions, 162 deletions
diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java
index 41dbca33d..75dfa6ac7 100644
--- a/src/com/android/camera/imageprocessor/PostProcessor.java
+++ b/src/com/android/camera/imageprocessor/PostProcessor.java
@@ -33,6 +33,7 @@ import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
+import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
@@ -58,6 +59,7 @@ import com.android.camera.MediaSaveService;
import com.android.camera.PhotoModule;
import com.android.camera.SettingsManager;
import com.android.camera.exif.ExifInterface;
+import com.android.camera.exif.Rational;
import com.android.camera.imageprocessor.filter.BestpictureFilter;
import com.android.camera.imageprocessor.filter.ChromaflashFilter;
import com.android.camera.imageprocessor.filter.OptizoomFilter;
@@ -71,12 +73,14 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.Semaphore;
import com.android.camera.imageprocessor.filter.ImageFilter;
import com.android.camera.util.CameraUtil;
+import android.util.Size;
public class PostProcessor{
@@ -109,25 +113,35 @@ public class PostProcessor{
private PhotoModule.NamedImages mNamedImages;
private WatchdogThread mWatchdog;
private int mOrientation = 0;
- private ImageWriter mZSLImageWriter;
+ private ImageWriter mImageWriter;
//This is for the debug feature.
private static boolean DEBUG_FILTER = false;
- private static boolean DEBUG_ZSL = false;
+ private static boolean DEBUG_ZSL = true;
private ImageFilter.ResultImage mDebugResultImage;
private ZSLQueue mZSLQueue;
private CameraDevice mCameraDevice;
private CameraCaptureSession mCaptureSession;
private ImageReader mImageReader;
+ private ImageReader mZSLReprocessImageReader;
private boolean mUseZSL = true;
private Handler mZSLHandler;
private HandlerThread mZSLHandlerThread;
private ImageHandlerTask mImageHandlerTask;
+ private LinkedList<TotalCaptureResult> mTotalCaptureResultList = new LinkedList<TotalCaptureResult>();
public boolean isZSLEnabled() {
return mUseZSL;
}
+ public void onStartCapturing() {
+ mTotalCaptureResultList.clear();
+ }
+
+ public ImageReader getZSLReprocessImageReader() {
+ return mZSLReprocessImageReader;
+ }
+
public ImageHandlerTask getImageHandler() {
return mImageHandlerTask;
}
@@ -158,24 +172,31 @@ public class PostProcessor{
@Override
public void onImageAvailable(ImageReader reader) {
try {
- Image image = reader.acquireLatestImage();
- if(image == null) {
- return;
- }
- if (!mMutureLock.tryAcquire()) {
- image.close();
- return;
- }
- if(mImageWrapper == null || mImageWrapper.isTaken()) {
- mImageWrapper = new ImageWrapper(image);
- mMutureLock.release();
- } else {
- image.close();
- mMutureLock.release();
- return;
- }
- if(mZSLHandler != null) {
- mZSLHandler.post(this);
+ if(mUseZSL) {
+ Image image = reader.acquireLatestImage();
+ if (image == null) {
+ return;
+ }
+ if (!mMutureLock.tryAcquire()) {
+ image.close();
+ return;
+ }
+ if (mImageWrapper == null || mImageWrapper.isTaken()) {
+ mImageWrapper = new ImageWrapper(image);
+ mMutureLock.release();
+ } else {
+ image.close();
+ mMutureLock.release();
+ return;
+ }
+ if (mZSLHandler != null) {
+ mZSLHandler.post(this);
+ }
+ } else { //Non ZSL case
+ Image image = reader.acquireNextImage();
+ if(image != null) {
+ onImageToProcess(image);
+ }
}
} catch (IllegalStateException e) {
Log.e(TAG, "Max images has been already acquired. ");
@@ -183,16 +204,14 @@ public class PostProcessor{
}
@Override
- public void run() {
+ public void run() { //Only ZSL case
+ Image image = mImageWrapper.getImage();
try {
mMutureLock.acquire();
- Image image = mImageWrapper.getImage();
if (mUseZSL) {
if (mZSLQueue != null) {
mZSLQueue.add(image);
}
- } else {
- onImageToProcess(image);
}
mMutureLock.release();
} catch (InterruptedException e) {
@@ -206,16 +225,52 @@ public class PostProcessor{
}
}
- public void onSessionConfiguredForZSL(CameraCaptureSession captureSession) {
- mZSLImageWriter = ImageWriter.newInstance(captureSession.getInputSurface(), 2);
+ CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session,
+ CaptureRequest request,
+ TotalCaptureResult result) {
+ if(mTotalCaptureResultList.size() <= PostProcessor.MAX_REQUIRED_IMAGE_NUM) {
+ mTotalCaptureResultList.add(result);
+ }
+ onMetaAvailable(result);
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session,
+ CaptureRequest request,
+ CaptureFailure result) {
+ }
+
+ @Override
+ public void onCaptureSequenceCompleted(CameraCaptureSession session, int
+ sequenceId, long frameNumber) {
+ mController.unlockFocus(mController.getMainCameraId());
+ }
+ };
+
+ public CameraCaptureSession.CaptureCallback getCaptureCallback() {
+ return mCaptureCallback;
}
- public boolean takeZSLPicture(CameraDevice cameraDevice, CameraCaptureSession captureSession, ImageReader imageReader) {
- if(mCameraDevice == null || mCaptureSession == null || mImageReader == null) {
- mCameraDevice = cameraDevice;
- mCaptureSession = captureSession;
- mImageReader = imageReader;
+ public void onSessionConfigured(CameraDevice cameraDevice, CameraCaptureSession captureSession) {
+ mCameraDevice = cameraDevice;
+ mCaptureSession = captureSession;
+ if(mUseZSL) {
+ mImageWriter = ImageWriter.newInstance(captureSession.getInputSurface(), 2);
+ }
+ }
+
+ public void onImageReaderReady(ImageReader imageReader, Size maxSize, Size pictureSize) {
+ mImageReader = imageReader;
+ if(mUseZSL) {
+ mZSLReprocessImageReader = ImageReader.newInstance(pictureSize.getWidth(), pictureSize.getHeight(), ImageFormat.YUV_420_888, 2);
+ mZSLReprocessImageReader.setOnImageAvailableListener(processedImageAvailableListener, mHandler);
}
+ }
+
+ public boolean takeZSLPicture() {
ZSLQueue.ImageItem imageItem = mZSLQueue.tryToGetMatchingItem();
if(mController.getPreviewCaptureResult() == null ||
mController.getPreviewCaptureResult().get(CaptureResult.CONTROL_AE_STATE) == CameraMetadata.CONTROL_AE_STATE_FLASH_REQUIRED) {
@@ -227,7 +282,7 @@ public class PostProcessor{
}
if (imageItem != null) {
if(DEBUG_ZSL) Log.d(TAG,"Got the item from the queue");
- reprocessImage(imageItem);
+ reprocessImage(imageItem.getImage(), imageItem.getMetadata());
return true;
} else {
if(DEBUG_ZSL) Log.d(TAG, "No good item in queue, register the request for the future");
@@ -237,19 +292,20 @@ public class PostProcessor{
}
public void onMatchingZSLPictureAvailable(ZSLQueue.ImageItem imageItem) {
- reprocessImage(imageItem);
+ reprocessImage(imageItem.getImage(), imageItem.getMetadata());
}
- private void reprocessImage(ZSLQueue.ImageItem imageItem) {
+ private void reprocessImage(Image image, TotalCaptureResult metadata) {
if(mCameraDevice == null || mCaptureSession == null || mImageReader == null) {
Log.e(TAG, "Reprocess request is called even before taking picture");
new Throwable().printStackTrace();
return;
}
+ Log.d(TAG, "reprocess Image request");
CaptureRequest.Builder builder = null;
try {
- builder = mCameraDevice.createReprocessCaptureRequest(imageItem.getMetadata());
- builder.addTarget(mImageReader.getSurface());
+ builder = mCameraDevice.createReprocessCaptureRequest(metadata);
+ builder.addTarget(mZSLReprocessImageReader.getSurface());
builder.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE,
CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
builder.set(CaptureRequest.EDGE_MODE,
@@ -257,35 +313,11 @@ public class PostProcessor{
builder.set(CaptureRequest.NOISE_REDUCTION_MODE,
CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
try {
- mZSLImageWriter.queueInputImage(imageItem.getImage());
+ mImageWriter.queueInputImage(image);
} catch(IllegalStateException e) {
Log.e(TAG, "Queueing more than it can have");
}
- mCaptureSession.capture(builder.build(),
- new CameraCaptureSession.CaptureCallback() {
- @Override
- public void onCaptureCompleted(
- CameraCaptureSession session,
- CaptureRequest request,
- TotalCaptureResult result) {
- super.onCaptureCompleted(session, request, result);
- Log.d(TAG, "Success to reprocess zsl image");
- try {
- onImageToProcess(mZSLImageWriter.dequeueInputImage());
- } catch(IllegalStateException e) {
- Log.e(TAG, "Dequeueing more than what it has");
- }
- }
-
- @Override
- public void onCaptureFailed(
- CameraCaptureSession session,
- CaptureRequest request,
- CaptureFailure failure) {
- super.onCaptureFailed(session, request, failure);
- Log.e(TAG, "failed to reprocess");
- }
- }, null);
+ mCaptureSession.capture(builder.build(), mCaptureCallback, mHandler);
} catch (CameraAccessException e) {
}
}
@@ -335,13 +367,20 @@ public class PostProcessor{
return mFilter.isManualMode();
}
- public void manualCapture(CaptureRequest.Builder builder, CameraCaptureSession captureSession,
- CameraCaptureSession.CaptureCallback callback, Handler handler) throws CameraAccessException{
- try {
- mFilter.manualCapture(builder, captureSession, callback, handler);
- } catch(IllegalStateException e) {
- Log.w(TAG, "Session is closed while taking manual pictures ");
- }
+ public void manualCapture(final CaptureRequest.Builder builder, final CameraCaptureSession captureSession,
+ final Handler handler) throws CameraAccessException{
+ mHandler.post(new Runnable() {
+ public void run() {
+ try {
+ mFilter.manualCapture(builder, captureSession, mCaptureCallback, handler);
+ } catch(IllegalStateException e) {
+ Log.w(TAG, "Session is closed while taking manual pictures ");
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
}
public boolean isFilterOn() {
@@ -352,20 +391,23 @@ public class PostProcessor{
}
public boolean isSelfieMirrorOn() {
- if (SettingsManager.getInstance().getValue(SettingsManager.KEY_SELFIEMIRROR).equalsIgnoreCase("on")) {
+ if (SettingsManager.getInstance() != null &&
+ SettingsManager.getInstance().getValue(SettingsManager.KEY_SELFIEMIRROR) != null &&
+ SettingsManager.getInstance().getValue(SettingsManager.KEY_SELFIEMIRROR).equalsIgnoreCase("on")) {
return true;
}
return false;
}
- public void onOpen(int postFilterId, boolean isLongShotOn, boolean isFlashModeOn) {
+ public void onOpen(int postFilterId, boolean isLongShotOn, boolean isFlashModeOn, boolean isTrackingFocusOn) {
mImageHandlerTask = new ImageHandlerTask();
- if(setFilter(postFilterId) || isLongShotOn || isFlashModeOn) {
+ if(setFilter(postFilterId) || isLongShotOn || isFlashModeOn || isTrackingFocusOn) {
mUseZSL = false;
} else {
mUseZSL = true;
}
+ Log.d(TAG,"ZSL is "+mUseZSL);
startBackgroundThread();
if(mUseZSL) {
mZSLQueue = new ZSLQueue(mController);
@@ -388,9 +430,13 @@ public class PostProcessor{
mZSLQueue.onClose();
mZSLQueue = null;
}
- if (mZSLImageWriter != null) {
- mZSLImageWriter.close();
- mZSLImageWriter = null;
+ if (mImageWriter != null) {
+ mImageWriter.close();
+ mImageWriter = null;
+ }
+ if(mZSLReprocessImageReader != null) {
+ mZSLReprocessImageReader.close();
+ mZSLReprocessImageReader = null;
}
mCameraDevice = null;
mCaptureSession = null;
@@ -422,7 +468,7 @@ public class PostProcessor{
}
if(isMonitor) {
counter++;
- if(counter >= 40) { //This is 4 seconds.
+ if(counter >= 100) { //This is 20 seconds.
bark();
break;
}
@@ -510,13 +556,13 @@ public class PostProcessor{
mFilter = new SharpshooterFilter(mController);
break;
case FILTER_UBIFOCUS:
- mFilter = new UbifocusFilter(mController, mActivity);
+ mFilter = new UbifocusFilter(mController, mActivity, this);
break;
case FILTER_STILLMORE:
mFilter = new StillmoreFilter(mController);
break;
case FILTER_BESTPICTURE:
- mFilter = new BestpictureFilter(mController, mActivity);
+ mFilter = new BestpictureFilter(mController, mActivity, this);
break;
case FILTER_CHROMAFLASH:
mFilter = new ChromaflashFilter(mController);
@@ -627,11 +673,32 @@ public class PostProcessor{
});
}
- public static byte[] addExifTags(byte[] jpeg, int orientationInDegree) {
+ public static byte[] addExifTags(byte[] jpeg, int orientationInDegree, TotalCaptureResult result) {
ExifInterface exif = new ExifInterface();
+ exif.addMakeAndModelTag();
exif.addOrientationTag(orientationInDegree);
exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, System.currentTimeMillis(),
TimeZone.getDefault());
+ if(result != null) {
+ if(result.get(CaptureResult.FLASH_MODE) != null) {
+ exif.addFlashTag(result.get(CaptureResult.FLASH_MODE) != CaptureResult.FLASH_MODE_OFF);
+ }
+ if(result.get(CaptureResult.LENS_FOCAL_LENGTH) != null) {
+ exif.addFocalLength(new Rational((int)(result.get(CaptureResult.LENS_FOCAL_LENGTH)*100), 100));
+ }
+ if(result.get(CaptureResult.CONTROL_AWB_MODE) != null) {
+ exif.addWhiteBalanceMode(result.get(CaptureResult.CONTROL_AWB_MODE));
+ }
+ if(result.get(CaptureResult.LENS_APERTURE) != null) {
+ exif.addAperture(new Rational((int)(result.get(CaptureResult.LENS_APERTURE)*100), 100));
+ }
+ if(result.get(CaptureResult.SENSOR_EXPOSURE_TIME) != null) {
+ exif.addExposureTime(new Rational(result.get(CaptureResult.SENSOR_EXPOSURE_TIME)/1000000, 1000));
+ }
+ if(result.get(CaptureResult.SENSOR_SENSITIVITY) != null) {
+ exif.addISO(result.get(CaptureResult.SENSOR_SENSITIVITY));
+ }
+ }
ByteArrayOutputStream jpegOut = new ByteArrayOutputStream();
try {
exif.writeExif(jpeg, jpegOut);
@@ -679,12 +746,7 @@ public class PostProcessor{
}
if(isSelfieMirrorOn() && !mController.isBackCamera()) {
- if(mController.getMainCameraCharacteristics() != null &&
- mController.getMainCameraCharacteristics().get(CameraCharacteristics.SENSOR_ORIENTATION) == 90) {
- nativeFlipNV21(resultImage.outBuffer.array(), resultImage.stride, resultImage.height, true);
- } else {
- nativeFlipNV21(resultImage.outBuffer.array(), resultImage.stride, resultImage.height, false);
- }
+ nativeFlipNV21(resultImage.outBuffer.array(), resultImage.stride, resultImage.height, resultImage.stride - resultImage.width, true);
}
}
//End processing FrameProessor filter
@@ -700,32 +762,94 @@ public class PostProcessor{
Log.d(TAG, "Result image is not valid.");
} else {
if(mFilter != null && DEBUG_FILTER) {
- bytes = nv21ToJpeg(mDebugResultImage, mOrientation);
+ bytes = nv21ToJpeg(mDebugResultImage, mOrientation, null);
mActivity.getMediaSaveService().addImage(
bytes, title + "_beforeApplyingFilter", date, null, mDebugResultImage.outRoi.width(), mDebugResultImage.outRoi.height(),
mOrientation, null, mediaSavedListener, contentResolver, "jpeg");
}
- bytes = nv21ToJpeg(resultImage, mOrientation);
+ bytes = nv21ToJpeg(resultImage, mOrientation, waitForMetaData(0));
mActivity.getMediaSaveService().addImage(
- bytes, title, date, null, resultImage.outRoi.width(), resultImage.outRoi.height(),
- mOrientation, null, mediaSavedListener, contentResolver, "jpeg");
- mController.updateThumbnailJpegData(bytes);
+ bytes, title, date, null, resultImage.outRoi.width(), resultImage.outRoi.height(),
+ mOrientation, null, mediaSavedListener, contentResolver, "jpeg");
+ mController.updateThumbnailJpegData(bytes);
}
}
}
});
}
- private byte[] nv21ToJpeg(ImageFilter.ResultImage resultImage, int orientation) {
+ public TotalCaptureResult waitForMetaData(int index) {
+ int timeout = 10; //100ms
+ while(timeout > 0) {
+ if (mTotalCaptureResultList.size() > index) {
+ return mTotalCaptureResultList.get(index);
+ }
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ }
+ timeout--;
+ }
+ if(mTotalCaptureResultList.size() == 0) {
+ return null;
+ }
+ return mTotalCaptureResultList.get(0);
+ }
+
+ private ImageFilter.ResultImage resizeImage(ImageFilter.ResultImage oldImage, Size newSize) {
+ ImageFilter.ResultImage newImage = new ImageFilter.ResultImage(
+ ByteBuffer.allocateDirect(newSize.getWidth() * newSize.getHeight() * 3/2),
+ new Rect(0, 0,
+ newSize.getWidth(), newSize.getHeight()),
+ newSize.getWidth(), newSize.getHeight(), newSize.getWidth());
+ int ratio = nativeResizeImage(oldImage.outBuffer.array(), newImage.outBuffer.array(),
+ oldImage.width, oldImage.height, oldImage.stride, newSize.getWidth(), newSize.getHeight());
+ newImage.outRoi = new Rect(oldImage.outRoi.left/ratio, oldImage.outRoi.top/ratio,
+ oldImage.outRoi.right/ratio, oldImage.outRoi.bottom/ratio);
+ if(newImage.width < newImage.outRoi.width()) {
+ newImage.outRoi.right = newImage.width;
+ }
+ if(newImage.height < newImage.outRoi.height()) {
+ newImage.outRoi.bottom = newImage.height;
+ }
+ Log.d(TAG, "Image is resized by SW with the ratio: "+ratio+" oldRoi: "+oldImage.outRoi.toString());
+ return newImage;
+ }
+
+ ImageReader.OnImageAvailableListener processedImageAvailableListener = new ImageReader.OnImageAvailableListener() {
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ Log.d(TAG, "ZSL image Reprocess is done");
+ Image image = reader.acquireNextImage();
+ if(image != null) {
+ onImageToProcess(image);
+ }
+ }
+ };
+
+ private byte[] nv21ToJpeg(ImageFilter.ResultImage resultImage, int orientation, TotalCaptureResult result) {
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);
+ if(isSelfieMirrorOn() && !mController.isBackCamera()) {
+ int t = resultImage.height - (resultImage.outRoi.top + resultImage.outRoi.height());
+ resultImage.outRoi = new Rect(resultImage.outRoi.left, t, resultImage.outRoi.right , resultImage.outRoi.height() + t);
+ }
+ im.compressToJpeg(resultImage.outRoi, getJpegQualityValue(), bos);
byte[] bytes = bos.getArray();
- bytes = addExifTags(bytes, orientation);
+ bytes = addExifTags(bytes, orientation, result);
return bytes;
}
+ public int getJpegQualityValue() {
+ int quality = 55;
+ if(SettingsManager.getInstance() != null && SettingsManager.getInstance().getValue(SettingsManager.KEY_JPEG_QUALITY) != null) {
+ String value = SettingsManager.getInstance().getValue(SettingsManager.KEY_JPEG_QUALITY);
+ int jpegQuality = mController.getQualityNumber(value);
+ }
+ return quality;
+ }
+
private class BitmapOutputStream extends ByteArrayOutputStream {
public BitmapOutputStream(int size) {
super(size);
@@ -736,7 +860,9 @@ public class PostProcessor{
}
}
- private native int nativeFlipNV21(byte[] buf, int stride, int height, boolean isVertical);
+ private native int nativeNV21Split(byte[] srcYVU, ByteBuffer yBuf, ByteBuffer vuBuf, int width, int height, int srcStride, int dstStride);
+ private native int nativeResizeImage(byte[] oldBuf, byte[] newBuf, int oldWidth, int oldHeight, int oldStride, int newWidth, int newHeight);
+ private native int nativeFlipNV21(byte[] buf, int stride, int height, int gap, boolean isVertical);
static {
System.loadLibrary("jni_imageutil");
}
diff --git a/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java b/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java
index d9c9f5cb8..fcb4a4900 100644
--- a/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/BestpictureFilter.java
@@ -28,6 +28,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.android.camera.imageprocessor.filter;
+import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.graphics.Rect;
@@ -38,6 +39,7 @@ import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
@@ -80,6 +82,8 @@ public class BestpictureFilter implements ImageFilter {
private ByteBuffer mBVU;
private Object mClosingLock = new Object();
private boolean mIsOn = false;
+ private PostProcessor mProcessor;
+ private ProgressDialog mProgressDialog;
private static void Log(String msg) {
if (DEBUG) {
@@ -87,9 +91,10 @@ public class BestpictureFilter implements ImageFilter {
}
}
- public BestpictureFilter(CaptureModule module, CameraActivity activity) {
+ public BestpictureFilter(CaptureModule module, CameraActivity activity, PostProcessor processor) {
mModule = module;
mActivity = activity;
+ mProcessor = processor;
mNamedImages = new PhotoModule.NamedImages();
}
@@ -126,6 +131,7 @@ public class BestpictureFilter implements ImageFilter {
@Override
public void deinit() {
Log("deinit");
+ dismissProgressDialog();
synchronized (mClosingLock) {
mIsOn = false;
}
@@ -135,53 +141,77 @@ public class BestpictureFilter implements ImageFilter {
public void addImage(final ByteBuffer bY, final ByteBuffer bVU, final int imageNum, Object param) {
Log("addImage");
if(imageNum == 0) {
+ showProgressDialog();
mOrientation = CameraUtil.getJpegRotation(mModule.getMainCameraId(), mModule.getDisplayOrientation());
mSavedCount = 0;
mBY = bY;
mBVU = bVU;
- }
- new Thread() {
- public void run() {
- synchronized (mClosingLock) {
- if (!mIsOn) {
- return;
+
+ long captureStartTime = System.currentTimeMillis();
+ mNamedImages.nameNewImage(captureStartTime);
+ PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
+ String title = (name == null) ? null : name.title;
+ long date = (name == null) ? -1 : name.date;
+ mActivity.getMediaSaveService().addImage(
+ nv21ToJpeg(mBY, mBVU, new Rect(0, 0, mWidth, mHeight), mOrientation, 0), title, date, null, mWidth, mHeight,
+ mOrientation, null, new MediaSaveService.OnMediaSavedListener() {
+ @Override
+ public void onMediaSaved(final Uri uri) {
+ if (uri != null) {
+ mActivity.notifyNewMedia(uri);
+ new Thread() {
+ public void run() {
+ while(mSavedCount < NUM_REQUIRED_IMAGE) {
+ try {
+ Thread.sleep(10);
+ } catch (Exception e) {
+ }
+ }
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ dismissProgressDialog();
+ startBestpictureActivity(uri);
+ }
+ });
+ }
+ }.start();
+
+ }
+ }
}
- saveToPrivateFile(imageNum, nv21ToJpeg(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation));
- mSavedCount++;
- }
- }
- }.start();
+ , mActivity.getContentResolver(), "jpeg");
+ }
+ ImageSaveTask t = new ImageSaveTask(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation, imageNum);
+ t.execute();
}
@Override
public ResultImage processImage() {
- long captureStartTime = System.currentTimeMillis();
- mNamedImages.nameNewImage(captureStartTime);
- PhotoModule.NamedImages.NamedEntity name = mNamedImages.getNextNameEntity();
- String title = (name == null) ? null : name.title;
- long date = (name == null) ? -1 : name.date;
- mActivity.getMediaSaveService().addImage(
- nv21ToJpeg(mBY, mBVU, new Rect(0, 0, mWidth, mHeight), mOrientation), title, date, null, mWidth, mHeight,
- mOrientation, null, new MediaSaveService.OnMediaSavedListener() {
- @Override
- public void onMediaSaved(Uri uri) {
- if (uri != null) {
- mActivity.notifyNewMedia(uri);
- }
- startBestpictureActivity(uri);
- }
+ return null;
+ }
+
+ private void showProgressDialog() {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mProgressDialog = ProgressDialog.show(mActivity, "", "Saving pictures...", true, false);
+ mProgressDialog.show();
+ }
+ });
+ }
+
+ private void dismissProgressDialog() {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
}
- , mActivity.getContentResolver(), "jpeg");
- while(mSavedCount < NUM_REQUIRED_IMAGE) {
- try {
- Thread.sleep(1);
- } catch (Exception e) {
}
- }
- return null;
+ });
}
private void startBestpictureActivity(Uri uri) {
+ Log("Start best picture activity");
Intent intent = new Intent();
intent.setData(uri);
intent.setClass(mActivity, BestpictureActivity.class);
@@ -200,7 +230,7 @@ public class BestpictureFilter implements ImageFilter {
@Override
public boolean isManualMode() {
- return false;
+ return true;
}
@Override
@@ -219,7 +249,7 @@ public class BestpictureFilter implements ImageFilter {
return mIsSupported;
}
- private byte[] nv21ToJpeg(ByteBuffer bY, ByteBuffer bVU, Rect roi, int orientation) {
+ private byte[] nv21ToJpeg(ByteBuffer bY, ByteBuffer bVU, Rect roi, int orientation, int imageIndex) {
ByteBuffer buf = ByteBuffer.allocate(mStrideY*mHeight*3/2);
buf.put(bY);
bY.rewind();
@@ -230,9 +260,9 @@ public class BestpictureFilter implements ImageFilter {
BitmapOutputStream bos = new BitmapOutputStream(1024);
YuvImage im = new YuvImage(buf.array(), ImageFormat.NV21,
mWidth, mHeight, new int[]{mStrideY, mStrideVU});
- im.compressToJpeg(roi, 50, bos);
+ im.compressToJpeg(roi, mProcessor.getJpegQualityValue(), bos);
byte[] bytes = bos.getArray();
- bytes = PostProcessor.addExifTags(bytes, orientation);
+ bytes = PostProcessor.addExifTags(bytes, orientation, mProcessor.waitForMetaData(imageIndex));
return bytes;
}
@@ -246,18 +276,53 @@ public class BestpictureFilter implements ImageFilter {
}
}
- private void saveToPrivateFile(final int index, final byte[] bytes) {
- String filesPath = mActivity.getFilesDir()+"/Bestpicture";
- File file = new File(filesPath);
- if(!file.exists()) {
- file.mkdir();
+ private class ImageSaveTask extends AsyncTask<Void, Void, byte[]> {
+ ByteBuffer bY;
+ ByteBuffer bVU;
+ Rect roi;
+ int orientation;
+ int imageNum;
+
+ public ImageSaveTask(ByteBuffer bY, ByteBuffer bVU, Rect roi, int orientation, int imageNum) {
+ this.bY = bY;
+ this.bVU = bVU;
+ this.roi = roi;
+ this.orientation = orientation;
+ this.imageNum = imageNum;
+ }
+
+ @Override
+ protected void onPreExecute() {
}
- file = new File(filesPath+"/"+NAMES[index]);
- try {
- FileOutputStream out = new FileOutputStream(file);
- out.write(bytes, 0, bytes.length);
- out.close();
- } catch (Exception e) {
+
+ @Override
+ protected byte[] doInBackground(Void... v) {
+ synchronized (mClosingLock) {
+ if (!mIsOn) {
+ return null;
+ }
+ return nv21ToJpeg(bY, bVU, roi, orientation, imageNum);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(byte[] bytes) {
+ if(bytes == null)
+ return;
+ String filesPath = mActivity.getFilesDir()+"/Bestpicture";
+ File file = new File(filesPath);
+ if(!file.exists()) {
+ file.mkdir();
+ }
+ file = new File(filesPath+"/"+NAMES[imageNum]);
+ try {
+ FileOutputStream out = new FileOutputStream(file);
+ out.write(bytes, 0, bytes.length);
+ out.close();
+ } catch (Exception e) {
+ }
+ mSavedCount++;
+ Log(imageNum+" image is saved");
}
}
}
diff --git a/src/com/android/camera/imageprocessor/filter/ChromaflashFilter.java b/src/com/android/camera/imageprocessor/filter/ChromaflashFilter.java
index 4f54eb108..ad4c9933a 100644
--- a/src/com/android/camera/imageprocessor/filter/ChromaflashFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/ChromaflashFilter.java
@@ -147,14 +147,10 @@ public class ChromaflashFilter implements ImageFilter{
CameraCaptureSession.CaptureCallback callback, Handler handler) throws CameraAccessException {
for(int i=0; i < NUM_REQUIRED_IMAGE; i++) {
if(i == 1) {
- waitTillGetImage(0);
mModule.setFlashModeToPreview(mModule.getMainCameraId(), true);
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
} else {
- if(i == 2) {
- waitTillGetImage(1);
- }
mModule.setFlashModeToPreview(mModule.getMainCameraId(), false);
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
@@ -163,15 +159,6 @@ public class ChromaflashFilter implements ImageFilter{
}
}
- private void waitTillGetImage(int imageNum) {
- while(mImageNum < imageNum) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- }
- }
- }
-
public static boolean isSupportedStatic() {
return mIsSupported;
}
diff --git a/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java b/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
index a4e0f8e1e..57da5c441 100644
--- a/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
+++ b/src/com/android/camera/imageprocessor/filter/UbifocusFilter.java
@@ -74,6 +74,7 @@ public class UbifocusFilter implements ImageFilter {
private int mOrientation = 0;
private float mMinFocusDistance = -1f;
private Object mClosingLock = new Object();
+ private PostProcessor mPostProcessor;
final String[] NAMES = {"00.jpg", "01.jpg", "02.jpg", "03.jpg",
"04.jpg", "DepthMapImage.y", "AllFocusImage.jpg"};
@@ -85,9 +86,10 @@ public class UbifocusFilter implements ImageFilter {
}
}
- public UbifocusFilter(CaptureModule module, CameraActivity activity) {
+ public UbifocusFilter(CaptureModule module, CameraActivity activity, PostProcessor processor) {
mModule = module;
mActivity = activity;
+ mPostProcessor = processor;
}
@Override
@@ -145,7 +147,7 @@ public class UbifocusFilter implements ImageFilter {
if(mOutBuf == null) {
return;
}
- saveToPrivateFile(imageNum, nv21ToJpeg(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation));
+ saveToPrivateFile(imageNum, nv21ToJpeg(bY, bVU, new Rect(0, 0, mWidth, mHeight), mOrientation, imageNum));
mSavedCount++;
}
}
@@ -164,7 +166,7 @@ public class UbifocusFilter implements ImageFilter {
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));
+ saveToPrivateFile(NAMES.length - 1, nv21ToJpeg(mOutBuf, null, new Rect(roi[0], roi[1], roi[0] + roi[2], roi[1] + roi[3]), mOrientation, 0));
mModule.setRefocusLastTaken(true);
}
while(mSavedCount < NUM_REQUIRED_IMAGE) {
@@ -228,7 +230,7 @@ public class UbifocusFilter implements ImageFilter {
return mIsSupported;
}
- private byte[] nv21ToJpeg(ByteBuffer bY, ByteBuffer bVU, Rect roi, int orientation) {
+ private byte[] nv21ToJpeg(ByteBuffer bY, ByteBuffer bVU, Rect roi, int orientation, int imageIndex) {
ByteBuffer buf = ByteBuffer.allocate(mStrideY*mHeight*3/2);
buf.put(bY);
bY.rewind();
@@ -239,9 +241,9 @@ public class UbifocusFilter implements ImageFilter {
BitmapOutputStream bos = new BitmapOutputStream(1024);
YuvImage im = new YuvImage(buf.array(), ImageFormat.NV21,
mWidth, mHeight, new int[]{mStrideY, mStrideVU});
- im.compressToJpeg(roi, 50, bos);
+ im.compressToJpeg(roi, mPostProcessor.getJpegQualityValue(), bos);
byte[] bytes = bos.getArray();
- bytes = PostProcessor.addExifTags(bytes, orientation);
+ bytes = PostProcessor.addExifTags(bytes, orientation, mPostProcessor.waitForMetaData(imageIndex));
return bytes;
}