更新时间:2023-11-30 16:04:52
好吧,在这里,我将为您编写一个教程,内容涉及使用图像.html rel = noreferrer>相机通过启用相机的一些常见功能。
Well, Here I'm going to write a tutorial for you about capturing an image using Camera by enabling some common features of camera.
第1步:创建一个预览类
Step 1 : Create a preview class
/**
* A basic Camera preview class
*/
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
startPreview();
}
public void resetCamera(Camera camera) {
mCamera = camera;
}
public void startPreview() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
步骤2:使用 FrameLayout
来保存预览。
Step 2 : Use FrameLayout
to hold the preview.
<FrameLayout
android:id="@+id/cameraPreview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
第3步:获取相机
并发送到预览类。您可能需要在通过相机之前设置所需的参数。
Step 3 : Get the camera
and send to the preview class. you may need to set the parameters that you need prior passing the camera.
/**
* Create our Preview view and set it as the content of UI.
*/
private void initCameraPreview(final int cameraId, final boolean createPreview) {
mCamera = getCameraInstance(cameraId);
setupCameraParameters(cameraId);
if (createPreview) {
mPreview = new CameraPreview(this, mCamera);
mPreviewHolder.addView(mPreview);
}
mReadyToCapture = true;
}
/**
* A safe way to get an instance of the Camera object.
*/
private Camera getCameraInstance(int cameraId) {
Camera c = null;
try {
c = Camera.open(cameraId); // attempt to get a Camera instance
} catch (Exception e) {
e.printStackTrace();
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
/**
* Measure and Setup the camera parameters.
*/
private void setupCameraParameters(int cameraId) {
boolean hasFlash;
Camera.Parameters parameters = mCamera.getParameters();
mPreviewSize = determineBestPreviewSize(parameters);
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
Camera.Size bestPictureSize = determineBestPictureSize(parameters);
parameters.setPictureSize(bestPictureSize.width, bestPictureSize.height);
hasFlash = Util.hasSystemFeature(this, PackageManager.FEATURE_CAMERA_FLASH);
if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
hasFlash = Util.hasFrontCameraFlash(parameters);
} else {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
if (hasFlash)
parameters.setFlashMode(mFlashMode);
int[] orientations = Util.getCameraDisplayOrientation(this, cameraId);
mDisplayOrientation = orientations[0];
mLayoutOrientation = orientations[1];
mCamera.setDisplayOrientation(mDisplayOrientation);
mCamera.setParameters(parameters);
}
private Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
return determineBestSize(sizes);
}
private Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
return determineBestSize(sizes);
}
private Camera.Size determineBestSize(List<Camera.Size> sizes) {
Camera.Size bestSize = null;
for (Camera.Size currentSize : sizes) {
boolean isDesiredRatio = (currentSize.width / 4) == (currentSize.height / 3);
boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width);
boolean isInBounds = currentSize.width <= PICTURE_SIZE_MAX_WIDTH;
if (isDesiredRatio && isInBounds && isBetterSize) {
bestSize = currentSize;
}
}
if (bestSize == null) {
return sizes.get(0);
}
return bestSize;
}
第4步:交换相机的写方法
Step 4 : Writing method for swapping camera
/**
* Swapping between system cameras
*/
private void swapCamera() {
if (!(Camera.getNumberOfCameras() > 1)) {
/* No front facing camera to switch.*/
return;
}
mReadyToCapture = false;
mCamera.stopPreview();
releaseCamera(false);
if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
else
mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
initCameraPreview(mCurrentCameraId, false);
mPreview.resetCamera(mCamera);
mPreview.startPreview();
}
第5步:切换闪光灯的方法
Step 5 : Method for toggling flash
/**
* Toggling camera flash to ON/OFF
*/
private void toggleFlash() {
if (Util.hasSystemFeature(this, PackageManager.FEATURE_CAMERA_FLASH)) {
Camera.Parameters parameters = mCamera.getParameters();
if (mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
if (!Util.hasFrontCameraFlash(parameters)) {
/* Front facing camera doesn\'t supported flash. */
return;
}
}
mReadyToCapture = false;
if (Camera.Parameters.FLASH_MODE_ON.equals(parameters.getFlashMode())) {
mFlashMode = Camera.Parameters.FLASH_MODE_OFF;
} else {
mFlashMode = Camera.Parameters.FLASH_MODE_ON;
}
mCameraHandler.post(new Runnable() {
@Override
public void run() {
mCamera.stopPreview();
releaseCamera(false);
initCameraPreview(mCurrentCameraId, false);
mPreview.resetCamera(mCamera);
mPreview.startPreview();
}
});
} else {
/* warning_no_flash */
}
}
第6步:在屏幕状态变化期间处理相机的方法
Step 6: Methods for handling camera during the states changes of a screen
/**
* Release the camera for other applications
*/
private void releaseCamera(boolean remove) {
if (mCamera != null) {
if (remove)
mPreview.getHolder().removeCallback(mPreview);
mCamera.release();
mCamera = null;
}
}
步骤7:实用程序类。
/**
* Check whether the given feature available in s/m
*
* @return Returns true if the devices supports the feature, else
* false.
*/
public static boolean hasSystemFeature(Context context, String feature) {
return context.getPackageManager().hasSystemFeature(feature);
}
/**
* Check whether front camera flash feature available in s/m
*/
public static boolean hasFrontCameraFlash(Camera.Parameters cameraParameters) {
boolean result = true;
if (cameraParameters.getFlashMode() == null) {
result = false;
}
List<String> supportedFlashModes = cameraParameters.getSupportedFlashModes();
if (supportedFlashModes == null || supportedFlashModes.isEmpty()
|| supportedFlashModes.size() == 1 &&
supportedFlashModes.get(0).equals(Camera.Parameters.FLASH_MODE_OFF)) {
result = false;
}
return result;
}
/**
* Showing camera in the same orientation as the display
*/
public static int[] getCameraDisplayOrientation(Activity activity,
int cameraId) {
Camera.CameraInfo info =
new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
return new int[]{result, degrees};
}
Step 8: Capturing
Step 8: Capturing
// Get an image from the camera
if (null != mCamera && mReadyToCapture) {
mCameraOrientationListener.rememberOrientation();
mCamera.takePicture(mShutter, null, mPicture)
}
/**
* Camera shutter sound callback,
* used to enable sound while capture
*/
private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
};
/**
* Camera picture callback
*/
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mReadyToCapture = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
int rotation = ((mCurrentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? mDisplayOrientation :
((360 - mDisplayOrientation) % 360)) + mCameraOrientationListener.getRememberedOrientation()
+ mLayoutOrientation) % 360;
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
}
}
};
Step 9: Camera orientation listener for handling image rotation
Step 9: Camera orientation listener for handling image rotation
/**
* Orientation listener to remember the device's orientation when the user presses
* the shutter button.
* <p/>
* The orientation will be normalized to return it in steps of 90 degrees
* (0, 90, 180, 270).
*/
public class CameraOrientationListener extends OrientationEventListener {
private int currentNormalizedOrientation;
private int rememberedNormalizedOrientation;
public CameraOrientationListener(Context context) {
super(context, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onOrientationChanged(int orientation) {
if (orientation != ORIENTATION_UNKNOWN) {
currentNormalizedOrientation = normalize(orientation);
}
}
private int normalize(int degrees) {
if (degrees > 315 || degrees <= 45) {
return 0;
}
if (degrees > 45 && degrees <= 135) {
return 90;
}
if (degrees > 135 && degrees <= 225) {
return 180;
}
if (degrees > 225 && degrees <= 315) {
return 270;
}
throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies.");
}
public void rememberOrientation() {
rememberedNormalizedOrientation = currentNormalizedOrientation;
}
public int getRememberedOrientation() {
return rememberedNormalizedOrientation;
}
}
Step 10: States handling
Step 10: States handling
@Override
public void onPause() {
super.onPause();
mReadyToCapture = false;
releaseCamera(true);
}
@Override
public void onResume() {
super.onResume();
removePreview();
mReadyToCapture = false;
smoothCameraLoading();
}
private void removePreview() {
mPreviewHolder.removeAllViews();
}
private void smoothCameraLoading() {
mCameraHandler.post(new Runnable() {
@Override
public void run() {
initCameraPreview(mCurrentCameraId, true);
}
});
}
Step 11: Instance variable used
Step 11: Instance variable used
private String mFlashMode = Camera.Parameters.FLASH_MODE_OFF;
private int mCurrentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
private int mDisplayOrientation;
private int mLayoutOrientation;
private boolean mReadyToCapture = false;
private Camera.Size mPreviewSize;
private FrameLayout mPreviewHolder;
private Camera mCamera;
private CameraPreview mPreview;
private Handler mCameraHandler;
private CameraOrientationListener mCameraOrientationListener;
private FrameLayout mRootView;