From 36ebcb11b15fb00d3a641499c0f8a16745a2fbb0 Mon Sep 17 00:00:00 2001 From: Doris Liu Date: Mon, 28 Oct 2013 14:44:24 -0700 Subject: Fix the mapping between preview UI and camera sensor Bug: 11409659 Change-Id: I46ae3d7797590d59befbdc394d5304f14a212a80 --- src/com/android/camera/FocusOverlayManager.java | 38 ++++++++++++++++--------- src/com/android/camera/PhotoController.java | 3 +- src/com/android/camera/PhotoModule.java | 5 ++-- src/com/android/camera/PhotoUI.java | 8 ++++-- src/com/android/camera/util/CameraUtil.java | 25 ++++++++++++++++ 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java index c223aea6b..edc2db7b7 100644 --- a/src/com/android/camera/FocusOverlayManager.java +++ b/src/com/android/camera/FocusOverlayManager.java @@ -76,8 +76,6 @@ public class FocusOverlayManager { private boolean mAeAwbLock; private Matrix mMatrix; - private int mPreviewWidth; // The width of the preview frame layout. - private int mPreviewHeight; // The height of the preview frame layout. private boolean mMirror; // true if the camera is front-facing. private int mDisplayOrientation; private List mFocusArea; // focus area in driver format @@ -93,6 +91,7 @@ public class FocusOverlayManager { private boolean mFocusDefault; private FocusUI mUI; + private final Rect mPreviewRect = new Rect(0, 0, 0, 0); public interface FocusUI { public boolean hasFaces(); @@ -159,13 +158,25 @@ public class FocusOverlayManager { } public void setPreviewSize(int previewWidth, int previewHeight) { - if (mPreviewWidth != previewWidth || mPreviewHeight != previewHeight) { - mPreviewWidth = previewWidth; - mPreviewHeight = previewHeight; + if (mPreviewRect.width() != previewWidth || mPreviewRect.height() != previewHeight) { + setPreviewRect(new Rect(0, 0, previewWidth, previewHeight)); + } + } + + /** This setter should be the only way to mutate mPreviewRect. */ + public void setPreviewRect(Rect previewRect) { + if (!mPreviewRect.equals(previewRect)) { + mPreviewRect.set(previewRect); setMatrix(); } } + /** Returns a copy of mPreviewRect so that outside class cannot modify preview + * rect except deliberately doing so through the setter. */ + public Rect getPreviewRect() { + return new Rect(mPreviewRect); + } + public void setMirror(boolean mirror) { mMirror = mirror; setMatrix(); @@ -177,10 +188,9 @@ public class FocusOverlayManager { } private void setMatrix() { - if (mPreviewWidth != 0 && mPreviewHeight != 0) { + if (mPreviewRect.width() != 0 && mPreviewRect.height() != 0) { Matrix matrix = new Matrix(); - CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, - mPreviewWidth, mPreviewHeight); + CameraUtil.prepareMatrix(matrix, mMirror, mDisplayOrientation, getPreviewRect()); // In face detection, the matrix converts the driver coordinates to UI // coordinates. In tap focus, the inverted matrix converts the UI // coordinates to driver coordinates. @@ -352,7 +362,7 @@ public class FocusOverlayManager { mState == STATE_SUCCESS || mState == STATE_FAIL)) { cancelAutoFocus(); } - if (mPreviewWidth == 0 || mPreviewHeight == 0) return; + if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) return; mFocusDefault = false; // Initialize mFocusArea. if (mFocusAreaSupported) { @@ -507,7 +517,7 @@ public class FocusOverlayManager { mUI.clearFocus(); // Initialize mFocusArea. if (mFocusAreaSupported) { - initializeFocusAreas(mPreviewWidth / 2, mPreviewHeight / 2); + initializeFocusAreas(mPreviewRect.centerX(), mPreviewRect.centerY()); } // Reset metering area when no specific region is selected. if (mMeteringAreaSupported) { @@ -518,8 +528,10 @@ public class FocusOverlayManager { private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) { int areaSize = (int) (getAreaSize() * areaMultiple); - int left = CameraUtil.clamp(x - areaSize / 2, 0, mPreviewWidth - areaSize); - int top = CameraUtil.clamp(y - areaSize / 2, 0, mPreviewHeight - areaSize); + int left = CameraUtil.clamp(x - areaSize / 2, mPreviewRect.left, + mPreviewRect.right - areaSize); + int top = CameraUtil.clamp(y - areaSize / 2, mPreviewRect.top, + mPreviewRect.bottom - areaSize); RectF rectF = new RectF(left, top, left + areaSize, top + areaSize); mMatrix.mapRect(rectF); @@ -529,7 +541,7 @@ public class FocusOverlayManager { private int getAreaSize() { // Recommended focus area size from the manufacture is 1/8 of the image // width (i.e. longer edge of the image) - return Math.max(mPreviewWidth, mPreviewHeight) / 8; + return Math.max(mPreviewRect.width(), mPreviewRect.height()) / 8; } /* package */ int getFocusState() { diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java index 291b5df49..833c82574 100644 --- a/src/com/android/camera/PhotoController.java +++ b/src/com/android/camera/PhotoController.java @@ -16,6 +16,7 @@ package com.android.camera; +import android.graphics.Rect; import android.view.View; import com.android.camera.ShutterButton.OnShutterButtonListener; @@ -54,7 +55,7 @@ public interface PhotoController extends OnShutterButtonListener { public void onCountDownFinished(); - public void onScreenSizeChanged(int width, int height); + public void onPreviewRectChanged(Rect previewRect); public void updateCameraOrientation(); diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index aeca3ddef..46d71383d 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; @@ -505,8 +506,8 @@ public class PhotoModule } @Override - public void onScreenSizeChanged(int width, int height) { - if (mFocusManager != null) mFocusManager.setPreviewSize(width, height); + public void onPreviewRectChanged(Rect previewRect) { + if (mFocusManager != null) mFocusManager.setPreviewRect(previewRect); } private void resetExposureCompensation() { diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index cd3b9a52f..39094457f 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -22,6 +22,7 @@ import android.content.DialogInterface; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; +import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.graphics.drawable.ColorDrawable; import android.hardware.Camera; @@ -131,8 +132,6 @@ public class PhotoUI implements PieListener, mPreviewWidth = width; mPreviewHeight = height; setTransformMatrix(width, height); - mController.onScreenSizeChanged((int) mSurfaceTextureUncroppedWidth, - (int) mSurfaceTextureUncroppedHeight); } } }; @@ -253,6 +252,11 @@ public class PhotoUI implements PieListener, scaleY = scaledTextureHeight / height; mMatrix.setScale(scaleX, scaleY, (float) width / 2, (float) height / 2); mTextureView.setTransform(mMatrix); + + // Calculate the new preview rectangle. + RectF previewRect = new RectF(0, 0, width, height); + mMatrix.mapRect(previewRect); + mController.onPreviewRectChanged(CameraUtil.rectFToRect(previewRect)); } @Override diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java index eff0c4078..cbc9ebe34 100644 --- a/src/com/android/camera/util/CameraUtil.java +++ b/src/com/android/camera/util/CameraUtil.java @@ -678,6 +678,16 @@ public class CameraUtil { rect.bottom = Math.round(rectF.bottom); } + public static Rect rectFToRect(RectF rectF) { + Rect rect = new Rect(); + rectFToRect(rectF, rect); + return rect; + } + + public static RectF rectToRectF(Rect r) { + return new RectF(r.left, r.top, r.right, r.bottom); + } + public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, int viewWidth, int viewHeight) { // Need mirror for front camera. @@ -690,6 +700,21 @@ public class CameraUtil { matrix.postTranslate(viewWidth / 2f, viewHeight / 2f); } + public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, + Rect previewRect) { + // Need mirror for front camera. + matrix.setScale(mirror ? -1 : 1, 1); + // This is the value for android.hardware.Camera.setDisplayOrientation. + matrix.postRotate(displayOrientation); + + // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). + // We need to map camera driver coordinates to preview rect coordinates + Matrix mapping = new Matrix(); + mapping.setRectToRect(new RectF(-1000, -1000, 1000, 1000), rectToRectF(previewRect), + Matrix.ScaleToFit.FILL); + matrix.setConcat(mapping, matrix); + } + public static String createJpegName(long dateTaken) { synchronized (sImageFileNamer) { return sImageFileNamer.generateName(dateTaken); -- cgit v1.2.3