diff options
Diffstat (limited to 'src/com/android/camera/ui/Camera2FaceView.java')
-rw-r--r-- | src/com/android/camera/ui/Camera2FaceView.java | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/com/android/camera/ui/Camera2FaceView.java b/src/com/android/camera/ui/Camera2FaceView.java new file mode 100644 index 000000000..40a3469aa --- /dev/null +++ b/src/com/android/camera/ui/Camera2FaceView.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.android.camera.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.hardware.camera2.params.Face; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; + +import com.android.camera.util.CameraUtil; + +public class Camera2FaceView extends FaceView { + + private Face[] mFaces; + private Face[] mPendingFaces; + private Rect mCameraBound; + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SWITCH_FACES: + mStateSwitchPending = false; + mFaces = mPendingFaces; + invalidate(); + break; + } + } + }; + + public Camera2FaceView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setCameraBound(Rect cameraBound) { + mCameraBound = cameraBound; + } + + public void setFaces(Face[] faces) { + if (LOGV) Log.v(TAG, "Num of faces=" + faces.length); + if (mPause) return; + if (mFaces != null) { + if ((faces.length > 0 && mFaces.length == 0) + || (faces.length == 0 && mFaces.length > 0)) { + mPendingFaces = faces; + if (!mStateSwitchPending) { + mStateSwitchPending = true; + mHandler.sendEmptyMessageDelayed(MSG_SWITCH_FACES, SWITCH_DELAY); + } + return; + } + } + if (mStateSwitchPending) { + mStateSwitchPending = false; + mHandler.removeMessages(MSG_SWITCH_FACES); + } + mFaces = faces; + if (!mBlocked && (mFaces != null) && (mFaces.length > 0) && mCameraBound != null) { + invalidate(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (!mBlocked && (mFaces != null) && (mFaces.length > 0) && mCameraBound != null) { + int rw, rh; + rw = mUncroppedWidth; + rh = mUncroppedHeight; + if (((rh > rw) && ((mDisplayOrientation == 0) || (mDisplayOrientation == 180))) + || ((rw > rh) && ((mDisplayOrientation == 90) || (mDisplayOrientation == 270)))) { + int temp = rw; + rw = rh; + rh = temp; + } + CameraUtil.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, rw, rh); + + // mMatrix assumes that the face coordinates are from -1000 to 1000. + // so translate the face coordination to match the assumption. + Matrix translateMatrix = new Matrix(); + translateMatrix.preTranslate(-mCameraBound.width() / 2f, -mCameraBound.height() / 2f); + translateMatrix.postScale(2000f / mCameraBound.width(), 2000f / mCameraBound.height()); + + int dx = (getWidth() - rw) / 2; + ; + int dy = (getHeight() - rh) / 2; + + // Focus indicator is directional. Rotate the matrix and the canvas + // so it looks correctly in all orientations. + canvas.save(); + mMatrix.postRotate(mOrientation); // postRotate is clockwise + canvas.rotate(-mOrientation); // rotate is counter-clockwise (for canvas) + for (int i = 0; i < mFaces.length; i++) { + if (mFaces[i].getScore() < 50) continue; + Rect faceBound = mFaces[i].getBounds(); + faceBound.offset(-mCameraBound.left, -mCameraBound.top); + mRect.set(faceBound); + translateMatrix.mapRect(mRect); + mMatrix.mapRect(mRect); + mPaint.setColor(mColor); + mRect.offset(dx, dy); + + canvas.drawOval(mRect, mPaint); + } + canvas.restore(); + } + super.onDraw(canvas); + } + + @Override + public void clear() { + // Face indicator is displayed during preview. Do not clear the + // drawable. + mColor = mFocusingColor; + mFaces = null; + invalidate(); + } +} |