From 7d80bdb6ca1db08ecd29389ac7f263ecff6c5b70 Mon Sep 17 00:00:00 2001 From: Jack Yoo Date: Wed, 13 Jul 2016 14:49:22 -0700 Subject: SnapdragonCamera: Selfie Mirror mode Selfie mirror menu for front camera1. Change-Id: I2e6845c9e25481106f51772b5d3dfd0a971a2be7 CRs-Fixed: 1050663 --- src/com/android/camera/CameraSettings.java | 1 + src/com/android/camera/PhotoMenu.java | 4 +- src/com/android/camera/PhotoModule.java | 40 ++++++++++++++++- .../camera/imageprocessor/FrameProcessor.java | 50 +++++++++------------- .../camera/imageprocessor/PostProcessor.java | 4 ++ 5 files changed, 67 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java index f700d2187..bf31724df 100644 --- a/src/com/android/camera/CameraSettings.java +++ b/src/com/android/camera/CameraSettings.java @@ -100,6 +100,7 @@ public class CameraSettings { public static final String KEY_DENOISE = "pref_camera_denoise_key"; public static final String KEY_BRIGHTNESS = "pref_camera_brightness_key"; public static final String KEY_REDEYE_REDUCTION = "pref_camera_redeyereduction_key"; + public static final String KEY_SELFIE_MIRROR = "pref_camera_selfiemirror_key"; public static final String KEY_CDS_MODE = "pref_camera_cds_mode_key"; public static final String KEY_VIDEO_CDS_MODE = "pref_camera_video_cds_mode_key"; public static final String KEY_TNR_MODE = "pref_camera_tnr_mode_key"; diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java index c2f9a538b..2c339f68b 100755 --- a/src/com/android/camera/PhotoMenu.java +++ b/src/com/android/camera/PhotoMenu.java @@ -191,7 +191,8 @@ public class PhotoMenu extends MenuController CameraSettings.KEY_EXPOSURE, CameraSettings.KEY_WHITE_BALANCE, CameraSettings.KEY_QC_CHROMA_FLASH, - CameraSettings.KEY_REDEYE_REDUCTION + CameraSettings.KEY_REDEYE_REDUCTION, + CameraSettings.KEY_SELFIE_MIRROR }; mOtherKeys2 = new String[] { @@ -234,6 +235,7 @@ public class PhotoMenu extends MenuController CameraSettings.KEY_MANUAL_EXPOSURE, CameraSettings.KEY_MANUAL_WB, CameraSettings.KEY_MANUAL_FOCUS, + CameraSettings.KEY_SELFIE_MIRROR, SettingsManager.KEY_CAMERA2 }; diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index b4f8c3a74..52e99ad1c 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -24,7 +24,10 @@ import android.content.Intent; import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; @@ -47,6 +50,7 @@ import android.os.Message; import android.os.MessageQueue; import android.os.SystemClock; import android.provider.MediaStore; +import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.OrientationEventListener; @@ -88,6 +92,7 @@ import android.text.TextUtils; import com.android.internal.util.MemInfoReader; import android.app.ActivityManager; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -1260,6 +1265,19 @@ public class PhotoModule } } + private byte[] flipJpeg(byte[] jpegData) { + Bitmap srcBitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); + Matrix m = new Matrix(); + m.preScale(-1, 1); + Bitmap dstBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), m, false); + dstBitmap.setDensity(DisplayMetrics.DENSITY_DEFAULT); + int size = dstBitmap.getWidth() * dstBitmap.getHeight(); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(size); + dstBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream); + + return outStream.toByteArray(); + } + private final class JpegPictureCallback implements CameraPictureCallback { Location mLocation; @@ -1269,7 +1287,7 @@ public class PhotoModule } @Override - public void onPictureTaken(final byte [] jpegData, CameraProxy camera) { + public void onPictureTaken(byte [] jpegData, CameraProxy camera) { mUI.stopSelfieFlash(); mUI.enableShutter(true); if (mUI.isPreviewCoverVisible()) { @@ -1361,6 +1379,16 @@ public class PhotoModule if (!mRefocus || (mRefocus && mReceivedSnapNum == 7)) { ExifInterface exif = Exif.getExif(jpegData); int orientation = Exif.getOrientation(exif); + if(mCameraId == CameraHolder.instance().getFrontCameraId()) { + IconListPreference selfieMirrorPref = (IconListPreference) mPreferenceGroup + .findPreference(CameraSettings.KEY_SELFIE_MIRROR); + if (selfieMirrorPref != null && selfieMirrorPref.getValue() != null && + selfieMirrorPref.getValue().equalsIgnoreCase("enable")) { + jpegData = flipJpeg(jpegData); + exif = Exif.getExif(jpegData); + exif.addOrientationTag(orientation); + } + } if (!mIsImageCaptureIntent) { // Burst snapshot. Generate new image name. if (mReceivedSnapNum > 1) { @@ -1973,8 +2001,16 @@ public class PhotoModule mUI.overrideSettings(CameraSettings.KEY_FLASH_MODE, flashMode); } - if(mCameraId != CameraHolder.instance().getFrontCameraId()) + if(mCameraId != CameraHolder.instance().getFrontCameraId()) { CameraSettings.removePreferenceFromScreen(mPreferenceGroup, CameraSettings.KEY_SELFIE_FLASH); + CameraSettings.removePreferenceFromScreen(mPreferenceGroup, CameraSettings.KEY_SELFIE_MIRROR); + } else { + ListPreference prefSelfieMirror = mPreferenceGroup.findPreference(CameraSettings.KEY_SELFIE_MIRROR); + if(prefSelfieMirror != null && prefSelfieMirror.getValue() != null + && prefSelfieMirror.getValue().equalsIgnoreCase("enable")) { + mUI.overrideSettings(CameraSettings.KEY_LONGSHOT, "off"); + } + } } private void overrideCameraSettings(final String flashMode, diff --git a/src/com/android/camera/imageprocessor/FrameProcessor.java b/src/com/android/camera/imageprocessor/FrameProcessor.java index 74db08b31..4bee19194 100644 --- a/src/com/android/camera/imageprocessor/FrameProcessor.java +++ b/src/com/android/camera/imageprocessor/FrameProcessor.java @@ -125,7 +125,7 @@ public class FrameProcessor { mOutingHandler = new Handler(mOutingThread.getLooper()); } - if(mListeningThread == null) { + if (mListeningThread == null) { mListeningThread = new HandlerThread("FrameListeningThread"); mListeningThread.start(); mListeningHandler = new Handler(mListeningThread.getLooper()); @@ -256,10 +256,10 @@ public class FrameProcessor { } catch (InterruptedException e) { } } - for(ImageFilter filter : mPreviewFilters) { + for (ImageFilter filter : mPreviewFilters) { filter.deinit(); } - for(ImageFilter filter : mFinalFilters) { + for (ImageFilter filter : mFinalFilters) { filter.deinit(); } } @@ -275,14 +275,14 @@ public class FrameProcessor { public List getInputSurfaces() { List surfaces = new ArrayList(); - if(mPreviewFilters.size() == 0 && mFinalFilters.size() == 0) { + if (mPreviewFilters.size() == 0 && mFinalFilters.size() == 0) { surfaces.add(mSurfaceAsItIs); - if(mIsVideoOn) { + if (mIsVideoOn) { surfaces.add(mVideoSurfaceAsItIs); } } else if (mFinalFilters.size() == 0) { surfaces.add(mSurfaceAsItIs); - if(mIsVideoOn) { + if (mIsVideoOn) { surfaces.add(mVideoSurfaceAsItIs); } surfaces.add(getReaderSurface()); @@ -293,7 +293,7 @@ public class FrameProcessor { } public boolean isFrameFilterEnabled() { - if(mFinalFilters.size() == 0) { + if (mFinalFilters.size() == 0) { return false; } return true; @@ -301,13 +301,13 @@ public class FrameProcessor { public void setOutputSurface(Surface surface) { mSurfaceAsItIs = surface; - if(mFinalFilters.size() != 0) { + if (mFinalFilters.size() != 0) { mOutputAllocation.setSurface(surface); } } public void setVideoOutputSurface(Surface surface) { - if(surface == null) { + if (surface == null) { synchronized (mAllocationLock) { if (mVideoOutputAllocation != null) { mVideoOutputAllocation.destroy(); @@ -319,7 +319,7 @@ public class FrameProcessor { } mVideoSurfaceAsItIs = surface; mIsVideoOn = true; - if(mFinalFilters.size() != 0) { + if (mFinalFilters.size() != 0) { synchronized (mAllocationLock) { if (mVideoOutputAllocation == null) { Type.Builder rgbTypeBuilder = new Type.Builder(mRs, Element.RGBA_8888(mRs)); @@ -346,32 +346,32 @@ public class FrameProcessor { @Override public void onImageAvailable(ImageReader reader) { synchronized (mAllocationLock) { - if(mOutputAllocation == null) { + if (mOutputAllocation == null) { return; } try { Image image = reader.acquireLatestImage(); - if(image == null) { + if (image == null) { return; } - if(!mIsActive) { + if (!mIsActive) { image.close(); return; } mIsAllocationEverUsed = true; ByteBuffer bY = image.getPlanes()[0].getBuffer(); ByteBuffer bVU = image.getPlanes()[2].getBuffer(); - if(yvuBytes == null || width != mSize.getWidth() || height != mSize.getHeight()) { + if (yvuBytes == null || width != mSize.getWidth() || height != mSize.getHeight()) { stride = image.getPlanes()[0].getRowStride(); width = mSize.getWidth(); height = mSize.getHeight(); ySize = stride * mSize.getHeight(); - yvuBytes = new byte[ySize*3/2]; + yvuBytes = new byte[ySize * 3 / 2]; } boolean needToFeedSurface = false; //Start processing yvu buf for (ImageFilter filter : mPreviewFilters) { - if(filter.isFrameListener()) { + if (filter.isFrameListener()) { if (mListeningTask.setParam(filter, bY, bVU, mSize.getWidth(), mSize.getHeight(), stride)) { mListeningHandler.post(mListeningTask); } @@ -384,7 +384,7 @@ public class FrameProcessor { bVU.rewind(); } //End processing yvu buf - if(needToFeedSurface) { + if (needToFeedSurface) { bY.get(yvuBytes, 0, bY.remaining()); bVU.get(yvuBytes, ySize, bVU.remaining()); mOutingHandler.post(this); @@ -398,17 +398,17 @@ public class FrameProcessor { @Override public void run() { synchronized (mAllocationLock) { - if(!mIsActive) { + if (!mIsActive) { return; } - if(mInputAllocation == null) { + if (mInputAllocation == null) { createAllocation(stride, height, stride - width); } mInputAllocation.copyFrom(yvuBytes); mRsRotator.forEach_rotate90andMerge(mInputAllocation); mRsYuvToRGB.forEach_nv21ToRgb(mOutputAllocation); mOutputAllocation.ioSend(); - if(mVideoOutputAllocation != null) { + if (mVideoOutputAllocation != null) { mVideoOutputAllocation.copyFrom(mOutputAllocation); mVideoOutputAllocation.ioSend(); } @@ -425,7 +425,7 @@ public class FrameProcessor { Semaphore mMutureLock = new Semaphore(1); public boolean setParam(ImageFilter filter, ByteBuffer bY, ByteBuffer bVU, int width, int height, int stride) { - if(!mIsActive) { + if (!mIsActive) { return false; } if (!mMutureLock.tryAcquire()) { @@ -467,13 +467,5 @@ public class FrameProcessor { } } } - - private native int nativeRotateNV21(ByteBuffer inBuf, int imageWidth, int imageHeight, int degree, ByteBuffer outBuf); - - private native int nativeNV21toRgb(ByteBuffer yvuBuf, ByteBuffer rgbBuf, int width, int height); - - static { - System.loadLibrary("jni_imageutil"); - } } diff --git a/src/com/android/camera/imageprocessor/PostProcessor.java b/src/com/android/camera/imageprocessor/PostProcessor.java index 8c0d2ff88..a1cea3530 100644 --- a/src/com/android/camera/imageprocessor/PostProcessor.java +++ b/src/com/android/camera/imageprocessor/PostProcessor.java @@ -488,5 +488,9 @@ public class PostProcessor implements ImageReader.OnImageAvailableListener{ } } + private native int nativeFlipVerticalNV21(byte[] buf, int stride, int height); + static { + System.loadLibrary("jni_imageutil"); + } } -- cgit v1.2.3