/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.example.rscamera; import android.app.Activity; import android.content.Context; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.TotalCaptureResult; import android.renderscript.RenderScript; import android.util.AttributeSet; import android.util.Log; import android.util.Size; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceHolder; import android.view.View; import com.android.example.rscamera.rscamera.R; import java.util.ArrayList; import java.util.List; /** * Created by hoford on 2/27/15. */ public class CameraView extends FixedAspectSurfaceView { private static final String TAG = "CameraPreView"; private static final long MICRO_SECOND = 1000; private static final long MILLI_SECOND = MICRO_SECOND * 1000; private static final long ONE_SECOND = MILLI_SECOND * 1000; private Surface mPreviewSurface; ViewfinderProcessor mProcessor; private Surface mProcessingNormalSurface; CameraOps mCameraOps; CameraManager mCameraManager; Activity mActivity; Context mContext; byte mode = 0; public static final byte MODE_NONE = 0; public static final byte MODE_SPEED = 1; public static final byte MODE_FOCUS = 2; public static final byte MODE_ISO = 3; RenderScript mRS; ErrorCallback mErrorCallback; ParametersChangedCallback mParametersChangedCallback; public CameraView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; mRS = RenderScript.create(mContext); SurfaceHolder.Callback callback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mPreviewSurface = holder.getSurface(); setupProcessor(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { mPreviewSurface = null; } }; getHolder().addCallback(callback); mCameraManager = (CameraManager) mContext.getSystemService(mContext.CAMERA_SERVICE); CameraOps.ErrorDisplayer errorDisplayer = new CameraOps.ErrorDisplayer() { @Override public void showErrorDialog(String errorMessage) { Log.v(TAG, "ERROR"); if (mErrorCallback != null) { mErrorCallback.showError(errorMessage); } //MessageDialogFragment.newInstance(errorMessage).show(getFragmentManager(), FRAGMENT_DIALOG); } @Override public String getErrorString(CameraAccessException e) { switch (e.getReason()) { case CameraAccessException.CAMERA_DISABLED: return mContext.getString(R.string.camera_disabled); case CameraAccessException.CAMERA_DISCONNECTED: return mContext.getString(R.string.camera_disconnected); case CameraAccessException.CAMERA_ERROR: return mContext.getString(R.string.camera_error); default: return mContext.getString(R.string.camera_unknown, e.getReason()); } } }; CameraOps.CameraReadyListener cameraReadyListener = new CameraOps.CameraReadyListener() { @Override public void onCameraReady() { mCameraOps.setUpCamera(mProcessingNormalSurface); } }; setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return touchScreen(event); } }); mCameraOps = new CameraOps(mCameraManager, errorDisplayer, cameraReadyListener); } public void resume(Activity activity) { mActivity = activity; String errorMessage = mCameraOps.resume(); if (errorMessage != null) { if (mErrorCallback != null) { mErrorCallback.showError(errorMessage); } } else { Size outputSize = mCameraOps.getBestSize(); mProcessor = new ViewfinderProcessor(mRS, outputSize); // Configure the output view - this will fire surfaceChanged setAspectRatio((float) outputSize.getWidth() / outputSize.getHeight()); getHolder().setFixedSize(outputSize.getWidth(), outputSize.getHeight()); } } public void pause() { mCameraOps.pause(); } /** * Once camera is open and output surfaces are ready, configure the RS processing * and the camera device inputs/outputs. */ private void setupProcessor() { if (mProcessor == null || mPreviewSurface == null) return; mProcessor.setOutputSurface(mPreviewSurface); mProcessingNormalSurface = mProcessor.getInputSurface(); mCameraOps.setSurface(mProcessingNormalSurface); } public void takePicture() { // Orientation int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation(); int jpegRotation = Surface.ROTATION_0; switch (rotation) { case 90: jpegRotation = Surface.ROTATION_0; break; case 0: jpegRotation = Surface.ROTATION_90; break; case 180: jpegRotation = Surface.ROTATION_270; break; case 270: jpegRotation = Surface.ROTATION_180; break; } String name = "Simple" + System.currentTimeMillis() + ".jpg"; mCameraOps.captureStillPicture(jpegRotation, name, mContext.getContentResolver()); } private CameraCaptureSession.CaptureCallback mPhotoCallback = new CameraCaptureSession.CaptureCallback() { public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { Log.v(TAG, "onCaptureCompleted " + result.toString()); } }; float mDownY; long mExposureDown; float mFocusDistDown; public boolean touchScreen(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mDownY = event.getY(); mExposureDown = mCameraOps.getExposure(); mFocusDistDown = mCameraOps.getFocusDistance(); if (mFocusDistDown == 0.0) { mFocusDistDown = 0.01f; } } float distanceY = event.getY() - mDownY; float width = getWidth(); float height = getHeight(); float yDistNorm = distanceY / height; float ACCELERATION_FACTOR = 8; float scaleFactor = (float) Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR); switch (mode) { case MODE_SPEED: long exp = (long) (mExposureDown * scaleFactor); exp = Math.min(mCameraOps.getExpMax(), exp); mCameraOps.setExposure(Math.max(mCameraOps.getExpMin(), exp)); Log.v(TAG, "mExposure =" + mCameraOps.getExposure()); break; case MODE_FOCUS: float focusDist = mFocusDistDown * scaleFactor; focusDist = Math.max(0.0f, Math.min(mCameraOps.getFocusMin(), focusDist)); if (focusDist < 0.01) focusDist = 0; mCameraOps.setFocusDistance(focusDist); Log.v(TAG, "mFocusDist =" + focusDist); break; case MODE_ISO: ACCELERATION_FACTOR = 2; scaleFactor = (float) Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR); int iso = (int) (getIso() * scaleFactor); iso = Math.min(mCameraOps.getIsoMax(), iso); mCameraOps.setIso(Math.max(mCameraOps.getIsoMin(), iso)); break; } if (mParametersChangedCallback != null) { mParametersChangedCallback.parametersChanged(); } mCameraOps.setParameters(); return true; } public void setMode(byte mode) { this.mode = mode; } public byte getMode() { return mode; } public int getIso() { return mCameraOps.getIso(); } public void setIso(int iso) { mCameraOps.setIso(iso); if (mParametersChangedCallback != null) { mParametersChangedCallback.parametersChanged(); } mCameraOps.setParameters(); } public long getExposure() { return mCameraOps.getExposure(); } public void setExposure(long exposure) { mCameraOps.setExposure(exposure); if (mParametersChangedCallback != null) { mParametersChangedCallback.parametersChanged(); } mCameraOps.setParameters(); } public float getFocusDist() { return mCameraOps.getFocusDistance(); } public void setFocusInMeters(float dist) { float min = mCameraOps.getFocusMin(); float d = 10 / (dist + 10 / min); setFocusDist(d); } public void setFocusDist(float dist) { mCameraOps.setFocusDistance(dist); mCameraOps.setParameters(); } public float getMinFocusDistance() { return mCameraOps.getFocusMin(); } public void setAutofocus(boolean autofocus) { mCameraOps.setAutoFocus(autofocus); mCameraOps.setParameters(); } public boolean isAutoExposure() { return mCameraOps.isAutoExposure(); } public boolean isAutofocus() { return mCameraOps.isAutoFocus(); } public void setAutoExposure(boolean autoExposure) { mCameraOps.setAutoExposure(autoExposure); mCameraOps.setParameters(); } public static interface ErrorCallback { public void showError(String errorMessage); } public void setErrorCallback(ErrorCallback errorCallback) { mErrorCallback = errorCallback; } public static interface ParametersChangedCallback { public void parametersChanged(); } public void setParametersChangedCallback(ParametersChangedCallback parametersChangedCallback) { mParametersChangedCallback = parametersChangedCallback; } float getFps() { return mProcessor.getmFps(); } }