package com.chris.video; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Rect; import android.hardware.Camera; import android.opengl.GLSurfaceView; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.SurfaceView; /** * */ public class SquareCameraPreview extends GLSurfaceView { public static final String TAG = SquareCameraPreview.class.getSimpleName(); private static final int INVALID_POINTER_ID = -1; private static final int ZOOM_OUT = 0; private static final int ZOOM_IN = 1; private static final int ZOOM_DELTA = 1; private static final int FOCUS_SQR_SIZE = 100; private static final int FOCUS_MAX_BOUND = 1000; private static final int FOCUS_MIN_BOUND = -FOCUS_MAX_BOUND; private static final double ASPECT_RATIO = 3.0 / 4.0; private Camera mCamera; private float mLastTouchX; private float mLastTouchY; // For scaling private int mMaxZoom; private boolean mIsZoomSupported; private int mActivePointerId = INVALID_POINTER_ID; private int mScaleFactor = 1; private ScaleGestureDetector mScaleDetector; // For focus private boolean mIsFocus; private Camera.Area mFocusArea; private ArrayList<Camera.Area> mFocusAreas; public SquareCameraPreview(Context context) { super(context); init(context); } public SquareCameraPreview(Context context, AttributeSet attrs) { super(context, attrs); init(context); } // public SquareCameraPreview(Context context, AttributeSet attrs, int defStyle) { // super(context, attrs, defStyle); // init(context); // } private void init(Context context) { mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); mFocusArea = new Camera.Area(new Rect(), 1000); mFocusAreas = new ArrayList<Camera.Area>(); mFocusAreas.add(mFocusArea); } /** * Measure the view and its content to determine the measured width and the * measured height */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if (width > height * ASPECT_RATIO) { width = (int) (height * ASPECT_RATIO + 0.5); } else { height = (int) (width / ASPECT_RATIO + 0.5); } setMeasuredDimension(width, height); } public int getViewWidth() { return getWidth(); } public int getViewHeight() { return getHeight(); } public void setCamera(Camera camera) { mCamera = camera; if (camera != null) { Camera.Parameters params = camera.getParameters(); mIsZoomSupported = params.isZoomSupported(); if (mIsZoomSupported) { mMaxZoom = params.getMaxZoom(); } } } @Override public boolean onTouchEvent(MotionEvent event) { mScaleDetector.onTouchEvent(event); final int action = event.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { mIsFocus = true; mLastTouchX = event.getX(); mLastTouchY = event.getY(); mActivePointerId = event.getPointerId(0); break; } case MotionEvent.ACTION_UP: { if (mIsFocus) { handleFocus(mCamera.getParameters()); } mActivePointerId = INVALID_POINTER_ID; break; } case MotionEvent.ACTION_POINTER_DOWN: { mCamera.cancelAutoFocus(); mIsFocus = false; break; } case MotionEvent.ACTION_CANCEL: { mActivePointerId = INVALID_POINTER_ID; break; } } return true; } private void handleZoom(Camera.Parameters params) { int zoom = params.getZoom(); if (mScaleFactor == ZOOM_IN) { if (zoom < mMaxZoom) zoom += ZOOM_DELTA; } else if (mScaleFactor == ZOOM_OUT) { if (zoom > 0) zoom -= ZOOM_DELTA; } params.setZoom(zoom); if (mCamera != null) { mCamera.setParameters(params); } } private void handleFocus(Camera.Parameters params) { float x = mLastTouchX; float y = mLastTouchY; if (!setFocusBound(x, y)) return; List<String> supportedFocusModes = params.getSupportedFocusModes(); if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { Log.d(TAG, mFocusAreas.size() + ""); params.setFocusAreas(mFocusAreas); params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); if (mCamera != null) { mCamera.setParameters(params); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // Callback when the auto focus completes } }); } } } private boolean setFocusBound(float x, float y) { int left = (int) (x - FOCUS_SQR_SIZE / 2); int right = (int) (x + FOCUS_SQR_SIZE / 2); int top = (int) (y - FOCUS_SQR_SIZE / 2); int bottom = (int) (y + FOCUS_SQR_SIZE / 2); if (FOCUS_MIN_BOUND > left || left > FOCUS_MAX_BOUND) return false; if (FOCUS_MIN_BOUND > right || right > FOCUS_MAX_BOUND) return false; if (FOCUS_MIN_BOUND > top || top > FOCUS_MAX_BOUND) return false; if (FOCUS_MIN_BOUND > bottom || bottom > FOCUS_MAX_BOUND) return false; mFocusArea.rect.set(left, top, right, bottom); return true; } private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { mScaleFactor = (int) detector.getScaleFactor(); if (mCamera != null) { handleZoom(mCamera.getParameters()); } return true; } } }