From 37c3c7cc832adbd8b78fa0a3e1f8d074111638d9 Mon Sep 17 00:00:00 2001 From: Likai Ding Date: Thu, 18 Dec 2014 23:25:22 +0800 Subject: SnapdragonCamera: support 4:3 preview on 16:9 screen When preview is set to 4:3 on a 16:9 screen, resize SurfaceView to 4:3 and cover other parts of the screen. Otherwise camera controls have a semi-transparent background. Change-Id: Icfbe6318b6a9de9a988468078b474e842f6ddd8c --- src/com/android/camera/PhotoUI.java | 139 ++++++++++++++++++-------- src/com/android/camera/VideoUI.java | 13 +++ src/com/android/camera/ui/CameraControls.java | 74 +++++++++++++- src/com/android/camera/util/CameraUtil.java | 32 ++++++ 4 files changed, 211 insertions(+), 47 deletions(-) (limited to 'src/com') diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 48b84a873..b4e08c398 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -26,6 +26,7 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.RectF; +import android.graphics.Point; import android.graphics.drawable.ColorDrawable; import android.hardware.Camera; import android.hardware.Camera.Face; @@ -144,23 +145,9 @@ public class PhotoUI implements PieListener, private boolean mUIhidden = false; private int mPreviewOrientation = -1; - // temporary variables for updating SurfaceView - private int mTempWidth; - private int mTempHeight; - - private final Handler mSurfaceViewUpdateHandler = new Handler(); - - private Runnable updateSurfaceView = new Runnable() { - - @Override - public void run() { - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mSurfaceView - .getLayoutParams(); - params.width = mTempWidth; - params.height = mTempHeight; - mSurfaceView.setLayoutParams(params); - } - }; + private int mScreenRatio = CameraUtil.RATIO_UNKNOWN; + private int mTopMargin = 0; + private int mBottomMargin = 0; public interface SurfaceTextureSizeChangedListener { public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight); @@ -196,7 +183,7 @@ public class PhotoUI implements PieListener, if (mOriginalPreviewHeight == 0) mOriginalPreviewHeight = height; mPreviewWidth = width; mPreviewHeight = height; - setTransformMatrix(mOriginalPreviewWidth, mOriginalPreviewHeight); + setTransformMatrix(mPreviewWidth, mPreviewHeight); mController.onScreenSizeChanged((int) mSurfaceTextureUncroppedWidth, (int) mSurfaceTextureUncroppedHeight); mAspectRatioResize = false; @@ -302,6 +289,18 @@ public class PhotoUI implements PieListener, mAnimationManager = new AnimationManager(); mOrientationResize = false; mPrevOrientationResize = false; + + Point size = new Point(); + mActivity.getWindowManager().getDefaultDisplay().getSize(size); + mScreenRatio = CameraUtil.determineRatio(size.x, size.y); + if (mScreenRatio == CameraUtil.RATIO_16_9) { + int l = size.x > size.y ? size.x : size.y; + int tm = mActivity.getResources().getDimensionPixelSize(R.dimen.preview_top_margin); + int bm = mActivity.getResources().getDimensionPixelSize(R.dimen.preview_bottom_margin); + mTopMargin = l / 4 * tm / (tm + bm); + mBottomMargin = l / 4 - mTopMargin; + } + mCameraControls.setMargins(mTopMargin, mBottomMargin); } public void updatePreviewThumbnail() { @@ -345,33 +344,76 @@ public class PhotoUI implements PieListener, mAspectRatioResize = true; mAspectRatio = ratio; } - - mSurfaceView.requestLayout(); + mCameraControls.setPreviewRatio(mAspectRatio); + layoutPreview(ratio); } - public void setSurfaceTextureSizeChangedListener(SurfaceTextureSizeChangedListener listener) { - mSurfaceTextureSizeListener = listener; - } - - private void setTransformMatrix(int width, int height) { - mMatrix = mSurfaceView.getMatrix(); - + public void layoutPreview(float ratio) { + FrameLayout.LayoutParams lp; float scaledTextureWidth, scaledTextureHeight; - if (mOrientationResize) { - scaledTextureWidth = height * mAspectRatio; - if (scaledTextureWidth > width) { - scaledTextureWidth = width; - scaledTextureHeight = scaledTextureWidth / mAspectRatio; - } else { - scaledTextureHeight = height; + int rotation = CameraUtil.getDisplayRotation(mActivity); + if (mScreenRatio == CameraUtil.RATIO_16_9 + && CameraUtil.determineRatio(ratio) == CameraUtil.RATIO_4_3) { + int l = (mTopMargin + mBottomMargin) * 4; + int s = l * 9 / 16; + switch (rotation) { + case 90: + lp = new FrameLayout.LayoutParams(l * 3 / 4, s); + lp.setMargins(mTopMargin, 0, mBottomMargin, 0); + scaledTextureWidth = l * 3 / 4; + scaledTextureHeight = s; + break; + case 180: + lp = new FrameLayout.LayoutParams(s, l * 3 / 4); + lp.setMargins(0, mBottomMargin, 0, mTopMargin); + scaledTextureWidth = s; + scaledTextureHeight = l * 3 / 4; + break; + case 270: + lp = new FrameLayout.LayoutParams(l * 3 / 4, s); + lp.setMargins(mBottomMargin, 0, mTopMargin, 0); + scaledTextureWidth = l * 3 / 4; + scaledTextureHeight = s; + break; + default: + lp = new FrameLayout.LayoutParams(s, l * 3 / 4); + lp.setMargins(0, mTopMargin, 0, mBottomMargin); + scaledTextureWidth = s; + scaledTextureHeight = l * 3 / 4; + break; } } else { - if (width > height) { - scaledTextureWidth = Math.max(width, height * mAspectRatio); - scaledTextureHeight = Math.max(height, width / mAspectRatio); + float width = mOriginalPreviewWidth, height = mOriginalPreviewHeight; + if (mOrientationResize) { + scaledTextureWidth = height * mAspectRatio; + if (scaledTextureWidth > width) { + scaledTextureWidth = width; + scaledTextureHeight = scaledTextureWidth / mAspectRatio; + } else { + scaledTextureHeight = height; + } } else { - scaledTextureWidth = Math.max(width, height / mAspectRatio); - scaledTextureHeight = Math.max(height, width * mAspectRatio); + if (width > height) { + scaledTextureWidth = Math.max(width, height * mAspectRatio); + scaledTextureHeight = Math.max(height, width / mAspectRatio); + } else { + scaledTextureWidth = Math.max(width, height / mAspectRatio); + scaledTextureHeight = Math.max(height, width * mAspectRatio); + } + } + + Log.v(TAG, "setTransformMatrix: scaledTextureWidth = " + scaledTextureWidth + + ", scaledTextureHeight = " + scaledTextureHeight); + + int orientation = mActivity.getResources().getConfiguration().orientation; + if (((rotation == 0 || rotation == 180) && scaledTextureWidth > scaledTextureHeight) + || ((rotation == 90 || rotation == 270) + && scaledTextureWidth < scaledTextureHeight)) { + lp = new FrameLayout.LayoutParams((int) scaledTextureHeight, + (int) scaledTextureWidth, Gravity.CENTER); + } else { + lp = new FrameLayout.LayoutParams((int) scaledTextureWidth, + (int) scaledTextureHeight, Gravity.CENTER); } } @@ -383,14 +425,23 @@ public class PhotoUI implements PieListener, mSurfaceTextureSizeListener.onSurfaceTextureSizeChanged( (int) mSurfaceTextureUncroppedWidth, (int) mSurfaceTextureUncroppedHeight); + Log.d(TAG, "mSurfaceTextureUncroppedWidth=" + mSurfaceTextureUncroppedWidth + + "mSurfaceTextureUncroppedHeight=" + mSurfaceTextureUncroppedHeight); } } - Log.v(TAG, "setTransformMatrix: scaledTextureWidth = " + scaledTextureWidth - + ", scaledTextureHeight = " + scaledTextureHeight); - mTempWidth = (int) scaledTextureWidth; - mTempHeight = (int) scaledTextureHeight; - mSurfaceViewUpdateHandler.post(updateSurfaceView); + mSurfaceView.setLayoutParams(lp); + if (mFaceView != null) { + mFaceView.setLayoutParams(lp); + } + } + + public void setSurfaceTextureSizeChangedListener(SurfaceTextureSizeChangedListener listener) { + mSurfaceTextureSizeListener = listener; + } + + private void setTransformMatrix(int width, int height) { + mMatrix = mSurfaceView.getMatrix(); // Calculate the new preview rectangle. RectF previewRect = new RectF(0, 0, width, height); diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 8a0eb8858..54a1bfcd4 100644 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -22,6 +22,7 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; +import android.graphics.Point; import android.graphics.drawable.ColorDrawable; import android.hardware.Camera.Parameters; import android.os.Handler; @@ -252,6 +253,14 @@ public class VideoUI implements PieRenderer.PieListener, mAnimationManager = new AnimationManager(); mOrientationResize = false; mPrevOrientationResize = false; + + Point size = new Point(); + mActivity.getWindowManager().getDefaultDisplay().getSize(size); + int l = size.x > size.y ? size.x : size.y; + int tm = mActivity.getResources().getDimensionPixelSize(R.dimen.preview_top_margin); + int bm = mActivity.getResources().getDimensionPixelSize(R.dimen.preview_bottom_margin); + int topMargin = l / 4 * tm / (tm + bm); + mCameraControls.setMargins(topMargin, l / 4 - topMargin); } public void updatePreviewThumbnail() { @@ -355,6 +364,8 @@ public class VideoUI implements PieRenderer.PieListener, if (mPreviewWidth > 0 && mPreviewHeight > 0) { mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX); } + // ensure a semi-transparent background for now + mCameraControls.setPreviewRatio(1.0f); } public int getPreviewWidth() { @@ -844,10 +855,12 @@ public class VideoUI implements PieRenderer.PieListener, } public void hideUIwhileRecording() { + mCameraControls.setWillNotDraw(true); mVideoMenu.hideUI(); } public void showUIafterRecording() { + mCameraControls.setWillNotDraw(false); mVideoMenu.showUI(); } diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java index 181bd991e..c2c33e785 100644 --- a/src/com/android/camera/ui/CameraControls.java +++ b/src/com/android/camera/ui/CameraControls.java @@ -21,6 +21,8 @@ import android.animation.Animator.AnimatorListener; import android.content.Context; import android.util.Log; import android.graphics.drawable.AnimationDrawable; +import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; @@ -32,6 +34,7 @@ import java.util.ArrayList; import org.codeaurora.snapcam.R; import com.android.camera.ui.ModuleSwitcher; import com.android.camera.ShutterButton; +import com.android.camera.util.CameraUtil; public class CameraControls extends RotatableLayout { @@ -69,6 +72,12 @@ public class CameraControls extends RotatableLayout { private TextView mRemainingPhotos; + private int mPreviewRatio; + private static int mTopMargin = 0; + private static int mBottomMargin = 0; + + private Paint mPaint; + AnimatorListener outlistener = new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { @@ -143,12 +152,12 @@ public class CameraControls extends RotatableLayout { public CameraControls(Context context, AttributeSet attrs) { super(context, attrs); - setMeasureAllChildren(true); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + setWillNotDraw(false); } public CameraControls(Context context) { - super(context); - setMeasureAllChildren(true); + this(context, null); } public static boolean isAnimating() { @@ -246,6 +255,32 @@ public class CameraControls extends RotatableLayout { layoutRemaingPhotos(); } + @Override + protected void onDraw(Canvas canvas) { + if (mTopMargin != 0) { + int rotation = getUnifiedRotation(); + int w = canvas.getWidth(), h = canvas.getHeight(); + switch (rotation) { + case 90: + canvas.drawRect(0, 0, mTopMargin, h, mPaint); + canvas.drawRect(w - mBottomMargin, 0, w, h, mPaint); + break; + case 180: + canvas.drawRect(0, 0, w, mBottomMargin, mPaint); + canvas.drawRect(0, h - mTopMargin, w, h, mPaint); + break; + case 270: + canvas.drawRect(0, 0, mBottomMargin, h, mPaint); + canvas.drawRect(w - mTopMargin, 0, w, h, mPaint); + break; + default: + canvas.drawRect(0, 0, w, mTopMargin, mPaint); + canvas.drawRect(0, h - mBottomMargin, w, h, mPaint); + break; + } + } + } + private void setLocation(int w, int h) { int rotation = getUnifiedRotation(); toIndex(mSwitcher, w, h, rotation, 4, 6, SWITCHER_INDEX); @@ -544,6 +579,23 @@ public class CameraControls extends RotatableLayout { int cx = (2 * windex + 1) * boxw / 2; int cy = (2 * hindex + 1) * boxh / 2; + if (index2 == 0 && mTopMargin != 0) { + switch (rotation) { + case 90: + cx = mTopMargin / 2; + break; + case 180: + cy = h - mTopMargin / 2; + break; + case 270: + cx = w - mTopMargin / 2; + break; + default: + cy = mTopMargin / 2; + break; + } + } + l = cx - tw / 2; r = cx + tw / 2; t = cy - th / 2; @@ -697,4 +749,20 @@ public class CameraControls extends RotatableLayout { getResources().getString(R.string.remaining_photos_format), remaining)); } } + + public void setMargins(int top, int bottom) { + mTopMargin = top; + mBottomMargin = bottom; + } + + public void setPreviewRatio(float ratio) { + int r = CameraUtil.determineRatio(ratio); + mPreviewRatio = r; + if (mPreviewRatio == CameraUtil.RATIO_4_3 && mTopMargin != 0) { + mPaint.setColor(getResources().getColor(R.color.camera_control_bg_opaque)); + } else { + mPaint.setColor(getResources().getColor(R.color.camera_control_bg_transparent)); + } + invalidate(); + } } diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java index 60d4f065c..08ce84d87 100644 --- a/src/com/android/camera/util/CameraUtil.java +++ b/src/com/android/camera/util/CameraUtil.java @@ -120,6 +120,10 @@ public class CameraUtil { /** Has to be in sync with the receiving MovieActivity. */ public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back"; + public static final int RATIO_UNKNOWN = 0; + public static final int RATIO_16_9 = 1; + public static final int RATIO_4_3 = 2; + public static boolean isSupported(String value, List supported) { return supported == null ? false : supported.indexOf(value) >= 0; } @@ -1067,4 +1071,32 @@ public class CameraUtil { public static boolean volumeKeyShutterDisable(Context context) { return context.getResources().getBoolean(R.bool.volume_key_shutter_disable); } + + public static int determineRatio(int width, int height) { + int s = width, l = height; + if (width > height) { + l = width; + s = height; + } + if (l * 3 == s * 4) { + return RATIO_4_3; + } else if (l * 9 == s * 16) { + return RATIO_16_9; + } else { + return RATIO_UNKNOWN; + } + } + + public static int determineRatio(float ratio) { + if (ratio < 1) { + ratio = 1 / ratio; + } + if (ratio > 1.33f && ratio < 1.34f) { + return RATIO_4_3; + } else if (ratio > 1.77f && ratio < 1.78f) { + return RATIO_16_9; + } else { + return RATIO_UNKNOWN; + } + } } -- cgit v1.2.3