diff options
-rw-r--r-- | jni/image_util_jni.cpp | 30 | ||||
-rw-r--r-- | res/drawable-hdpi/ic_settings_selfiemirror.png | bin | 0 -> 1480 bytes | |||
-rw-r--r-- | res/drawable-xhdpi/ic_settings_selfiemirror.png | bin | 0 -> 2329 bytes | |||
-rw-r--r-- | res/drawable-xxhdpi/ic_settings_selfiemirror.png | bin | 0 -> 3215 bytes | |||
-rw-r--r-- | res/values/qcomarrays.xml | 10 | ||||
-rw-r--r-- | res/values/qcomstrings.xml | 6 | ||||
-rw-r--r-- | res/xml/camera_preferences.xml | 7 | ||||
-rw-r--r-- | src/com/android/camera/CameraSettings.java | 1 | ||||
-rwxr-xr-x | src/com/android/camera/PhotoMenu.java | 4 | ||||
-rw-r--r-- | src/com/android/camera/PhotoModule.java | 40 | ||||
-rw-r--r-- | src/com/android/camera/imageprocessor/FrameProcessor.java | 50 | ||||
-rw-r--r-- | src/com/android/camera/imageprocessor/PostProcessor.java | 4 |
12 files changed, 120 insertions, 32 deletions
diff --git a/jni/image_util_jni.cpp b/jni/image_util_jni.cpp index 2297f9164..a4779b3d7 100644 --- a/jni/image_util_jni.cpp +++ b/jni/image_util_jni.cpp @@ -44,6 +44,8 @@ JNIEXPORT jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nat jint imageWidth, jint imageHeight, jint degree, jobjectArray outBuf); JNIEXPORT jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nativeNV21toRgb( JNIEnv *env, jobject thiz, jobjectArray yvuBuf, jobjectArray rgbBuf, jint width, jint height); +JNIEXPORT jint JNICALL Java_com_android_camera_imageprocessor_PostProcessor_nativeFlipVerticalNV21( + JNIEnv* env, jobject thiz, jbyteArray yvuBytes, jint width, jint height); #ifdef __cplusplus } #endif @@ -150,4 +152,32 @@ jint JNICALL Java_com_android_camera_imageprocessor_FrameProcessor_nativeNV21toR } } return 0; +} + +jint JNICALL Java_com_android_camera_imageprocessor_PostProcessor_nativeFlipVerticalNV21( + JNIEnv* env, jobject thiz, jbyteArray yvuBytes, jint width, jint height) +{ + jbyte* imageDataNV21Array = env->GetByteArrayElements(yvuBytes, NULL); + uint8_t *buf = (uint8_t *)imageDataNV21Array; + int ysize = width * height; + uint8_t temp1, temp2; + for(int x=0; x < width; x++) { + for(int y=0; y < height/2; y++) { + temp1 = buf[y*width + x]; + buf[y*width + x] = buf[(height-1-y)*width + x]; + buf[(height-1-y)*width + x] = temp1; + } + } + for(int x=0; x < width; x+=2) { + for(int y=0; y < height/4; y++) { + temp1 = buf[ysize + y*width + x]; + temp2 = buf[ysize + y*width + x + 1]; + buf[ysize + y*width + x] = buf[ysize + (height/2-1-y)*width + x]; + buf[ysize + y*width + x + 1] = buf[ysize + (height/2-1-y)*width + x + 1]; + buf[ysize + (height/2-1-y)*width + x] = temp1; + buf[ysize + (height/2-1-y)*width + x + 1] = temp2; + } + } + env->ReleaseByteArrayElements(yvuBytes, imageDataNV21Array, JNI_ABORT); + return 0; }
\ No newline at end of file diff --git a/res/drawable-hdpi/ic_settings_selfiemirror.png b/res/drawable-hdpi/ic_settings_selfiemirror.png Binary files differnew file mode 100644 index 000000000..c6d0f8be7 --- /dev/null +++ b/res/drawable-hdpi/ic_settings_selfiemirror.png diff --git a/res/drawable-xhdpi/ic_settings_selfiemirror.png b/res/drawable-xhdpi/ic_settings_selfiemirror.png Binary files differnew file mode 100644 index 000000000..975448e94 --- /dev/null +++ b/res/drawable-xhdpi/ic_settings_selfiemirror.png diff --git a/res/drawable-xxhdpi/ic_settings_selfiemirror.png b/res/drawable-xxhdpi/ic_settings_selfiemirror.png Binary files differnew file mode 100644 index 000000000..b49b6fa4a --- /dev/null +++ b/res/drawable-xxhdpi/ic_settings_selfiemirror.png diff --git a/res/values/qcomarrays.xml b/res/values/qcomarrays.xml index 7574992b9..4858ab3c0 100644 --- a/res/values/qcomarrays.xml +++ b/res/values/qcomarrays.xml @@ -587,6 +587,16 @@ <item>disable</item> <item>enable</item> </string-array> + + <string-array name="pref_camera_selfiemirror_entries" translatable="false"> + <item>@string/pref_camera_selfiemirror_entry_disable</item> + <item>@string/pref_camera_selfiemirror_entry_enable</item> + </string-array> + <string-array name="pref_camera_selfiemirror_entryvalues" translatable="false"> + <item>disable</item> + <item>enable</item> + </string-array> + <!-- Camera Preferences Selectable Zone AF dialog box entries --> <string-array name="pref_camera_selectablezoneaf_entries" translatable="false"> <item>@string/pref_camera_selectablezoneaf_entry_auto</item> diff --git a/res/values/qcomstrings.xml b/res/values/qcomstrings.xml index 0fb750590..e03a47344 100644 --- a/res/values/qcomstrings.xml +++ b/res/values/qcomstrings.xml @@ -322,6 +322,12 @@ <!-- Settings menu, redeye reduction choices --> <string name="pref_camera_redeyereduction_entry_enable">Enable</string> <string name="pref_camera_redeyereduction_entry_disable">Disable</string> + + <string name="pref_camera_selfiemirror_default" translatable="false">disable</string> + <string name="pref_camera_selfiemirror_title" translatable="true">Selfie Mirror</string> + <string name="pref_camera_selfiemirror_entry_enable">Enable</string> + <string name="pref_camera_selfiemirror_entry_disable">Disable</string> + <!-- Default mce setting. Do not translate. --> <string name="pref_camera_mce_default">enable</string> diff --git a/res/xml/camera_preferences.xml b/res/xml/camera_preferences.xml index 7e024b298..9c6d64670 100644 --- a/res/xml/camera_preferences.xml +++ b/res/xml/camera_preferences.xml @@ -285,6 +285,13 @@ camera:entries="@array/pref_camera_redeyereduction_entries" camera:singleIcon="@drawable/ic_settings_redeye" camera:entryValues="@array/pref_camera_redeyereduction_entryvalues" /> + <IconListPreference + camera:key="pref_camera_selfiemirror_key" + camera:defaultValue="@string/pref_camera_selfiemirror_default" + camera:title="@string/pref_camera_selfiemirror_title" + camera:entries="@array/pref_camera_selfiemirror_entries" + camera:singleIcon="@drawable/ic_settings_selfiemirror" + camera:entryValues="@array/pref_camera_selfiemirror_entryvalues" /> <ListPreference camera:key="pref_camera_selectablezoneaf_key" camera:defaultValue="@string/pref_camera_selectablezoneaf_default" 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<Surface> getInputSurfaces() { List<Surface> surfaces = new ArrayList<Surface>(); - 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"); + } } |