Skip to content
This repository has been archived by the owner on Nov 15, 2022. It is now read-only.

Commit

Permalink
Fix focus area in front camera.
Browse files Browse the repository at this point in the history
Front camera preview is mirrored. Change to use matrix to
calculate the focus area. So the focus area will be
correct in all orientations in front or back camera.

bug:5446617
bug:5461028
Change-Id: I2d39a22cd9f034c5028843ca3d4abe0f9962f18a
  • Loading branch information
Chih-yu Huang authored and Wu-cheng Li committed Oct 21, 2011
1 parent 7d9eadd commit 048edf2
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 43 deletions.
5 changes: 4 additions & 1 deletion src/com/android/camera/Camera.java
Expand Up @@ -377,7 +377,10 @@ private void initializeFirstTime() {
mPreviewFrame = findViewById(R.id.camera_preview);
mPreviewFrame.setOnTouchListener(this);
mFocusIndicator = (RotateLayout) findViewById(R.id.focus_indicator_rotate_layout);
mFocusManager.initialize(mFocusIndicator, mPreviewFrame, mFaceView, this);
CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId];
boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
mFocusManager.initialize(mFocusIndicator, mPreviewFrame, mFaceView, this,
mirror, mDisplayOrientation);
mFocusManager.initializeSoundPlayer(getResources().openRawResourceFd(R.raw.camera_focus));
mImageSaver = new ImageSaver();
Util.initializeScreenBrightness(getWindow(), getContentResolver());
Expand Down
40 changes: 23 additions & 17 deletions src/com/android/camera/FocusManager.java
Expand Up @@ -21,7 +21,9 @@
import com.android.camera.ui.FocusIndicatorView;

import android.content.res.AssetFileDescriptor;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera.Area;
import android.hardware.Camera.Parameters;
import android.os.Handler;
Expand Down Expand Up @@ -57,6 +59,7 @@ public class FocusManager {
private boolean mInLongPress;
private boolean mLockAeAwbNeeded;
private boolean mAeAwbLock;
private Matrix mMatrix;
private SoundPlayer mSoundPlayer;
private View mFocusIndicatorRotateLayout;
private FocusIndicatorView mFocusIndicator;
Expand Down Expand Up @@ -98,6 +101,7 @@ public FocusManager(ComboPreferences preferences, String defaultFocusMode) {
mPreferences = preferences;
mDefaultFocusMode = defaultFocusMode;
mHandler = new MainHandler();
mMatrix = new Matrix();
}

// This has to be initialized before initialize().
Expand All @@ -111,13 +115,22 @@ && isSupported(Parameters.FOCUS_MODE_AUTO,
}

public void initialize(View focusIndicatorRotate, View previewFrame,
FaceView faceView, Listener listener) {
FaceView faceView, Listener listener, boolean mirror, int displayOrientation) {
mFocusIndicatorRotateLayout = focusIndicatorRotate;
mFocusIndicator = (FocusIndicatorView) focusIndicatorRotate.findViewById(
R.id.focus_indicator);
mPreviewFrame = previewFrame;
mFaceView = faceView;
mListener = listener;

Matrix matrix = new Matrix();
Util.prepareMatrix(matrix, mirror, displayOrientation,
previewFrame.getWidth(), previewFrame.getHeight());
// 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.
matrix.invert(mMatrix);

if (mParameters != null) {
mInitialized = true;
} else {
Expand Down Expand Up @@ -270,9 +283,9 @@ public boolean onTouch(MotionEvent e) {
// Convert the coordinates to driver format.
// AE area is bigger because exposure is sensitive and
// easy to over- or underexposure if area is too small.
calculateTapArea(focusWidth, focusHeight, 1, x, y, previewWidth, previewHeight,
calculateTapArea(focusWidth, focusHeight, 1f, x, y, previewWidth, previewHeight,
mFocusArea.get(0).rect);
calculateTapArea(focusWidth, focusHeight, 1.5, x, y, previewWidth, previewHeight,
calculateTapArea(focusWidth, focusHeight, 1.5f, x, y, previewWidth, previewHeight,
mMeteringArea.get(0).rect);

// Use margin to set the focus indicator to the touched area.
Expand Down Expand Up @@ -451,23 +464,16 @@ public void resetTouchFocus() {
mMeteringArea = null;
}

public void calculateTapArea(int focusWidth, int focusHeight, double areaMultiple,
public void calculateTapArea(int focusWidth, int focusHeight, float areaMultiple,
int x, int y, int previewWidth, int previewHeight, Rect rect) {
int areaWidth = (int)(focusWidth * areaMultiple);
int areaHeight = (int)(focusHeight * areaMultiple);
int areaLeft = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
int areaTop = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);
convertToFocusArea(areaLeft, areaTop, areaWidth, areaHeight, previewWidth, previewHeight,
rect);
}

// Convert the touch point to the focus area in driver format.
public static void convertToFocusArea(int left, int top, int focusWidth, int focusHeight,
int previewWidth, int previewHeight, Rect rect) {
rect.left = Math.round((float) left / previewWidth * 2000 - 1000);
rect.top = Math.round((float) top / previewHeight * 2000 - 1000);
rect.right = Math.round((float) (left + focusWidth) / previewWidth * 2000 - 1000);
rect.bottom = Math.round((float) (top + focusHeight) / previewHeight * 2000 - 1000);
int left = Util.clamp(x - areaWidth / 2, 0, previewWidth - areaWidth);
int top = Util.clamp(y - areaHeight / 2, 0, previewHeight - areaHeight);

RectF rectF = new RectF(left, top, left + areaWidth, top + areaHeight);
mMatrix.mapRect(rectF);
Util.rectFToRect(rectF, rect);
}

public boolean isFocusCompleted() {
Expand Down
14 changes: 14 additions & 0 deletions src/com/android/camera/Util.java
Expand Up @@ -27,6 +27,8 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
Expand Down Expand Up @@ -522,6 +524,18 @@ public static void viewUri(Uri uri, Context context) {
}
}

public static void dumpRect(RectF rect, String msg) {
Log.v(TAG, msg + "=(" + rect.left + "," + rect.top
+ "," + rect.right + "," + rect.bottom + ")");
}

public static void rectFToRect(RectF rectF, Rect rect) {
rect.left = Math.round(rectF.left);
rect.top = Math.round(rectF.top);
rect.right = Math.round(rectF.right);
rect.bottom = Math.round(rectF.bottom);
}

public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation,
int viewWidth, int viewHeight) {
// Need mirror for front camera.
Expand Down
12 changes: 3 additions & 9 deletions src/com/android/camera/ui/FaceView.java
Expand Up @@ -117,17 +117,11 @@ public void resume() {
mPause = false;
}

private void dumpRect(RectF rect, String msg) {
Log.v(TAG, msg + "=(" + rect.left + "," + rect.top
+ "," + rect.right + "," + rect.bottom + ")");
}

@Override
protected void onDraw(Canvas canvas) {
if (mFaces != null && mFaces.length > 0) {
// Prepare the matrix.
Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, getWidth(),
getHeight());
Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, getWidth(), getHeight());

// Focus indicator is directional. Rotate the matrix and the canvas
// so it looks correctly in all orientations.
Expand All @@ -137,9 +131,9 @@ protected void onDraw(Canvas canvas) {
for (int i = 0; i < mFaces.length; i++) {
// Transform the coordinates.
mRect.set(mFaces[i].rect);
if (LOGV) dumpRect(mRect, "Original rect");
if (LOGV) Util.dumpRect(mRect, "Original rect");
mMatrix.mapRect(mRect);
if (LOGV) dumpRect(mRect, "Transformed rect");
if (LOGV) Util.dumpRect(mRect, "Transformed rect");

mFaceIndicator.setBounds(Math.round(mRect.left), Math.round(mRect.top),
Math.round(mRect.right), Math.round(mRect.bottom));
Expand Down
16 changes: 0 additions & 16 deletions tests/src/com/android/camera/unittest/CameraTest.java
Expand Up @@ -73,22 +73,6 @@ public void testRoundOrientation() {
assertEquals(180, Util.roundOrientation(180, 270));
}

public void testConvertToFocusArea() {
Rect rect = new Rect();
FocusManager.convertToFocusArea(0, 0, 100, 100, 800, 480, rect);
assertEquals(new Rect(-1000, -1000, -750, -583), rect);
FocusManager.convertToFocusArea(0, 0, 400, 240, 800, 480, rect);
assertEquals(new Rect(-1000, -1000, 0, 0), rect);
FocusManager.convertToFocusArea(400, 240, 400, 240, 800, 480, rect);
assertEquals(new Rect(0, 0, 1000, 1000), rect);
FocusManager.convertToFocusArea(200, 120, 400, 240, 800, 480, rect);
assertEquals(new Rect(-500, -500, 500, 500), rect);
FocusManager.convertToFocusArea(0, 0, 800, 480, 800, 480, rect);
assertEquals(new Rect(-1000, -1000, 1000, 1000), rect);
FocusManager.convertToFocusArea(860, 620, 100, 100, 960, 720, rect);
assertEquals(new Rect(792, 722, 1000, 1000), rect);
}

public void testPrepareMatrix() {
Matrix matrix = new Matrix();
float[] points;
Expand Down

0 comments on commit 048edf2

Please sign in to comment.