<color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
<color name="bright_foreground_holo_dark">#fff3f3f3</color>
<color name="face_detect_start">#ffffff00</color>
- <color name="face_detect_success">#8050d060</color>
- <color name="face_detect_fail">#80d05060</color>
+ <color name="focus_debug">#90ffffff</color>
+ <color name="focus_debug_light">#50ffffff</color>
+ <color name="focus_debug_success">#9000ff00</color>
+ <color name="focus_debug_fail">#90ff0000</color>
<color name="gray">#FFAAAAAA</color>
<!-- Camera mode switcher -->
<dimen name="focus_inner_stroke">2dp</dimen>
<dimen name="switcher_size">72dp</dimen>
<dimen name="face_circle_stroke">1dip</dimen>
+ <dimen name="focus_debug_stroke">1dip</dimen>
<dimen name="shutter_offset">-22dp</dimen>
<dimen name="size_thumbnail">200dip</dimen>
<dimen name="size_preview">400dip</dimen>
private static final int RESET_TOUCH_FOCUS = 0;
private static final int RESET_TOUCH_FOCUS_DELAY = 4000;
+ /**
+ * Size of AF region as multiple of shortest edge.
+ * Was 0.125 * longest edge prior to L release.
+ * TODO: Move to GservicesHelper
+ */
+ private static final float AF_REGION_BOX = 0.2f;
+
+ /** How much wider the touch metering area is relative to the AF area. */
+ public static final float AE_MULTIPLIER = 1.5f;
private int mState = STATE_IDLE;
private static final int STATE_IDLE = 0; // Focus is not active.
public interface FocusUI {
public boolean hasFaces();
public void clearFocus();
+ public void setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize);
public void setFocusPosition(int x, int y, boolean isPassiveScan);
public void onFocusStarted();
public void onFocusSucceeded();
// animate on false->true trasition only b/8219520
if (moving && !mPreviousMoving) {
// Auto focus at the center of the preview.
- mUI.setFocusPosition(mPreviewRect.centerX(), mPreviewRect.centerY(), true);
+ mUI.setFocusPosition(mPreviewRect.centerX(), mPreviewRect.centerY(), true,
+ getAFRegionEdge(), getAERegionEdge());
mUI.onFocusStarted();
} else if (!moving) {
mUI.onFocusSucceeded();
mPreviousMoving = moving;
}
+ /** Returns width of auto focus region in pixels. */
+ private int getAFRegionEdge() {
+ return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AF_REGION_BOX);
+ }
+
+ /** Returns width of metering region in pixels. */
+ private int getAERegionEdge() {
+ // Convert the coordinates to driver format.
+ // AE area is bigger by AE_MULTIPLIER because exposure is sensitive and
+ // easy to over- or underexposure if area is too small.
+ return (int) (Math.min(mPreviewRect.width(), mPreviewRect.height()) * AF_REGION_BOX
+ * AE_MULTIPLIER);
+ }
+
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void initializeFocusAreas(int x, int y) {
if (mFocusArea == null) {
}
// Convert the coordinates to driver format.
- calculateTapArea(x, y, 1f, mFocusArea.get(0).rect);
+ calculateTapArea(x, y, getAFRegionEdge(), mFocusArea.get(0).rect);
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
}
// 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(x, y, 1.5f, mMeteringArea.get(0).rect);
+ calculateTapArea(x, y, getAERegionEdge(), mMeteringArea.get(0).rect);
}
public void onSingleTapUp(int x, int y) {
}
// Use margin to set the focus indicator to the touched area.
- mUI.setFocusPosition(x, y, false);
+ mUI.setFocusPosition(x, y, false, getAFRegionEdge(), getAERegionEdge());
// Log manual tap to focus.
mTouchCoordinate = new TouchCoordinate(x, y, mPreviewRect.width(), mPreviewRect.height());
mTouchTime = System.currentTimeMillis();
}
}
- private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) {
- int areaSize = (int) (getAreaSize() * areaMultiple);
- int left = CameraUtil.clamp(x - areaSize / 2, mPreviewRect.left,
- mPreviewRect.right - areaSize);
- int top = CameraUtil.clamp(y - areaSize / 2, mPreviewRect.top,
- mPreviewRect.bottom - areaSize);
+ private void calculateTapArea(int x, int y, int size, Rect rect) {
+ int left = CameraUtil.clamp(x - size / 2, mPreviewRect.left,
+ mPreviewRect.right - size);
+ int top = CameraUtil.clamp(y - size / 2, mPreviewRect.top,
+ mPreviewRect.bottom - size);
- RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
+ RectF rectF = new RectF(left, top, left + size, top + size);
mMatrix.mapRect(rectF);
CameraUtil.rectFToRect(rectF, rect);
}
- 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(mPreviewRect.width(), mPreviewRect.height()) / 8;
- }
-
/* package */ int getFocusState() {
return mState;
}
private Face[] mFaces;
private Face[] mPendingFaces;
private int mColor;
- private final int mFocusingColor;
- private final int mFocusedColor;
- private final int mFailColor;
private Paint mPaint;
private volatile boolean mBlocked;
public FaceView(Context context, AttributeSet attrs) {
super(context, attrs);
Resources res = getResources();
- mFocusingColor = res.getColor(R.color.face_detect_start);
- mFocusedColor = res.getColor(R.color.face_detect_success);
- mFailColor = res.getColor(R.color.face_detect_fail);
- mColor = mFocusingColor;
+ mColor = res.getColor(R.color.face_detect_start);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.STROKE);
@Override
public void showStart() {
- mColor = mFocusingColor;
invalidate();
}
// Ignore the parameter. No autofocus animation for face detection.
@Override
public void showSuccess(boolean timeout) {
- mColor = mFocusedColor;
invalidate();
}
// Ignore the parameter. No autofocus animation for face detection.
@Override
public void showFail(boolean timeout) {
- mColor = mFailColor;
invalidate();
}
public void clear() {
// Face indicator is displayed during preview. Do not clear the
// drawable.
- mColor = mFocusingColor;
mFaces = null;
invalidate();
}
import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import com.android.camera.FocusOverlayManager;
+import com.android.camera.debug.DebugPropertyHelper;
import com.android.camera.debug.Log;
import com.android.camera2.R;
public class FocusOverlay extends View implements FocusOverlayManager.FocusUI {
private static final Log.Tag TAG = new Log.Tag("FocusOverlay");
+ /** System Properties switch to enable debugging focus UI. */
+ private static final boolean CAPTURE_DEBUG_UI = DebugPropertyHelper.showCaptureDebugUI();
+
private final static int FOCUS_DURATION_MS = 500;
private final static int FOCUS_INDICATOR_ROTATION_DEGREES = 50;
private final Drawable mFocusIndicator;
- private final Drawable mFocusOuterRing;
+ private Drawable mFocusOuterRing;
private final Rect mBounds = new Rect();
private final ValueAnimator mFocusAnimation = new ValueAnimator();
+ private Paint mDebugPaint;
+ private Paint mDebugAEPaint;
+ private int mDebugStartColor;
+ private int mDebugPassiveColor;
+ private int mDebugSuccessColor;
+ private int mDebugFailColor;
+ private Rect mFocusDebugAFRect;
+ private Rect mFocusDebugAERect;
+ private boolean mIsPassiveScan;
+
private int mPositionX;
private int mPositionY;
private int mAngle;
mFocusIndicatorSize = getResources().getDimensionPixelSize(R.dimen.focus_inner_ring_size);
mFocusOuterRing = getResources().getDrawable(R.drawable.focus_ring_touch_outer);
mFocusOuterRingSize = getResources().getDimensionPixelSize(R.dimen.focus_outer_ring_size);
+
+ if (CAPTURE_DEBUG_UI) {
+ Resources res = getResources();
+ mDebugStartColor = res.getColor(R.color.focus_debug);
+ mDebugPassiveColor = res.getColor(R.color.focus_debug_light);
+ mDebugSuccessColor = res.getColor(R.color.focus_debug_success);
+ mDebugFailColor = res.getColor(R.color.focus_debug_fail);
+ mDebugPaint = new Paint();
+ mDebugPaint.setColor(res.getColor(R.color.focus_debug));
+ mDebugPaint.setAntiAlias(true);
+ mDebugPaint.setStyle(Paint.Style.STROKE);
+ mDebugPaint.setStrokeWidth(res.getDimension(R.dimen.focus_debug_stroke));
+ mDebugAEPaint = new Paint(mDebugPaint);
+ mDebugAEPaint.setColor(res.getColor(R.color.focus_debug));
+ mFocusDebugAFRect = new Rect();
+ mFocusDebugAERect = new Rect();
+ }
}
@Override
@Override
public void clearFocus() {
mShowIndicator = false;
+ if (CAPTURE_DEBUG_UI) {
+ setVisibility(INVISIBLE);
+ }
}
@Override
public void setFocusPosition(int x, int y, boolean isPassiveScan) {
+ setFocusPosition(x, y, isPassiveScan, 0, 0);
+ }
+
+ @Override
+ public void setFocusPosition(int x, int y, boolean isPassiveScan, int aFsize, int aEsize) {
+ mIsPassiveScan = isPassiveScan;
mPositionX = x;
mPositionY = y;
mBounds.set(x - mFocusIndicatorSize / 2, y - mFocusIndicatorSize / 2,
mFocusIndicator.setBounds(mBounds);
mFocusOuterRing.setBounds(x - mFocusOuterRingSize / 2, y - mFocusOuterRingSize / 2,
x + mFocusOuterRingSize / 2, y + mFocusOuterRingSize / 2);
+
+ if (CAPTURE_DEBUG_UI) {
+ mFocusOuterRing.setBounds(0, 0, 0, 0);
+ mFocusDebugAFRect.set(x - aFsize / 2, y - aFsize / 2, x + aFsize / 2, y + aFsize / 2);
+ // If AE region is different size than AF region and active scan.
+ if (aFsize != aEsize && !isPassiveScan) {
+ mFocusDebugAERect.set(x - aEsize / 2, y - aEsize / 2, x + aEsize / 2,
+ y + aEsize / 2);
+ } else {
+ mFocusDebugAERect.set(0, 0, 0, 0);
+ }
+ mDebugPaint.setColor(isPassiveScan ? mDebugPassiveColor : mDebugStartColor);
+ }
+
if (getVisibility() != VISIBLE) {
setVisibility(VISIBLE);
}
public void onFocusSucceeded() {
mFocusAnimation.cancel();
mShowIndicator = false;
+ if (CAPTURE_DEBUG_UI && !mIsPassiveScan) {
+ mDebugPaint.setColor(mDebugSuccessColor);
+ }
invalidate();
}
public void onFocusFailed() {
mFocusAnimation.cancel();
mShowIndicator = false;
+ if (CAPTURE_DEBUG_UI && !mIsPassiveScan) {
+ mDebugPaint.setColor(mDebugFailColor);
+ }
invalidate();
}
mFocusIndicator.draw(canvas);
canvas.restore();
}
+ if (CAPTURE_DEBUG_UI && mFocusDebugAFRect != null) {
+ canvas.drawRect(mFocusDebugAFRect, mDebugPaint);
+ float delta = 0.1f * mFocusDebugAERect.width();
+ float left = mFocusDebugAERect.left;
+ float top = mFocusDebugAERect.top;
+ float right = mFocusDebugAERect.right;
+ float bot = mFocusDebugAERect.bottom;
+
+ canvas.drawLines(new float[]{left, top + delta, left, top, left, top, left + delta, top}, mDebugAEPaint);
+ canvas.drawLines(new float[]{right, top + delta, right, top, right, top, right - delta, top}, mDebugAEPaint);
+ canvas.drawLines(new float[]{left, bot - delta, left, bot, left, bot, left + delta, bot}, mDebugAEPaint);
+ canvas.drawLines(new float[]{right, bot - delta, right, bot, right, bot, right - delta, bot}, mDebugAEPaint);
+ }
}
}