赞
踩
CameraX 是一个 Jetpack 支持库,旨在帮助您简化相机应用的开发工作。它提供一致且易于使用的 API Surface,适用于大多数 Android 设备,并可向后兼容至 Android 5.0(API 级别 21)。
虽然它利用的是 camera2 的功能,但使用的是更为简单且基于用例的方法,该方法具有生命周期感知能力。它还解决了设备兼容性问题,因此您无需在代码库中添加设备专属代码。这些功能减少了将相机功能添加到应用时需要编写的代码量。
//主要工具类
implementation 'androidx.camera:camera-core:1.0.0-alpha10'
//主要的外部接口
implementation 'androidx.camera:camera-camera2:1.0.0-alpha10'
//管理相机的生命周期
implementation 'androidx.camera:camera-lifecycle:1.0.0-alpha10'
//预览图层
implementation 'androidx.camera:camera-view:1.0.0-alpha10'
//可选插件,通过该插件,您可以在支持的设备上添加效果。这些效果包括人像、HDR、夜间模式和美颜。
implementation 'androidx.camera:camera-extensions:1.0.0-alpha10'
各版本接口可能略有差别,但是功能基本保持一致。此外还需要申请相机权限:
<uses-permission android:name="android.permission.CAMERA" />
如果要拍照保存的话,还需要存储权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
private PreviewView previewView;
private ImageCapture imageCapture;
private ProcessCameraProvider cameraProvider;
cameraProviderFuture = ProcessCameraProvider.getInstance(activity);
cameraProviderFuture.addListener(() -> {
try {
cameraProvider = cameraProviderFuture.get();
//相机ID CameraSelector.LENS_FACING_FRONT前置;CameraSelector.LENS_FACING_BACK 后置
bindPreview(cameraProvider, cameraId);
} catch (ExecutionException | InterruptedException e) {
Log.e(TAG, "error:" + e);
}
}, ContextCompat.getMainExecutor(activity));
private void bindPreview(@NonNull ProcessCameraProvider cameraProvider, int lensFacing) { Preview preview = new Preview.Builder() .setTargetAspectRatio(AspectRatio.RATIO_16_9) //设置宽高比 .setTargetRotation(Surface.ROTATION_0) // 设置旋转角度 .build(); CameraSelector cameraSelector = new CameraSelector.Builder() .requireLensFacing(lensFacing) .build(); /** 图像分析可以分为两种模式:阻塞模式和非阻塞模式。通过使用 STRATEGY_BLOCK_PRODUCER 调用 setBackpressureStrategy() 以启用阻塞模式。 在此模式下,执行程序会按顺序从相机接收帧;这意味着,如果 analyze() 方法所用的时间超过单帧在当前帧 速率下的延迟时间,帧便可能不再是最新的帧,因为新帧已被阻止进入流水线,直到该方法返回为止。 通过使用 STRATEGY_KEEP_ONLY_LATEST 调用 setBackpressureStrategy() 以启用非阻塞模式。在此模式 下,执行程序会从相机接收调用 analyze() 方法时的最后一个可用帧。如果此方法所用的时间超过单帧在当前 帧速率下的延迟时间, 可能会跳过某些帧,以便在下一次 analyze() 接收数据时,它会获取相机流水线中的 最后一个可用帧。从 analyze() 返回前,请通过调用 image.close() 关闭图片引用,以避免阻塞其他图像的 生成(导致预览停顿)并避免可能出现的图像丢失。 此方法必须完成分析或创建副本,而不是将图像引用传递 到分析方法以外。*/ //设置宽高比 // 设置旋转角度 ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() .setTargetAspectRatio(AspectRatio.RATIO_16_9) //设置宽高比 .setTargetRotation(Surface.ROTATION_0) // 设置旋转角度 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build(); imageAnalysis.setAnalyzer(executors, imageProxy -> { //预览过程中,如果需要录制视频,则在这里获取。 //将图片转换成yuv(格式YUV_420_888)数据,再进行编码。 //如果处理数据太慢,导致造成阻塞,可以设置监听器,把数据发送到其他线程进行处理 ImageProxy.PlaneProxy[] planes = imageProxy.getPlanes(); byte[] mYuvBytes = new byte[imageProxy.getWidth() * imageProxy.getHeight() * 3 / 2]; // YUV_420_888 ByteBuffer yBuffer = planes[0].getBuffer(); int yLen = imageProxy.getWidth() * imageProxy.getHeight(); yBuffer.get(mYuvBytes, 0, yLen); ByteBuffer uBuffer = planes[1].getBuffer(); ByteBuffer vBuffer = planes[2].getBuffer(); int pixelStride = planes[1].getPixelStride(); // pixelStride = 2 for (int i = 0; i <= uBuffer.remaining(); i += pixelStride) { mYuvBytes[yLen++] = uBuffer.get(i); mYuvBytes[yLen++] = vBuffer.get(i); } imageProxy.close(); }); //拍摄图像的配置 imageCapture = new ImageCapture.Builder() //CAPTURE_MODE_MAXIMIZE_QUALITY 拍摄高质量图片,图像质量优先于延迟,可能需要更长的时间 //CAPTURE_MODE_MINIMIZE_LATENCY .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY) .setTargetAspectRatio(AspectRatio.RATIO_16_9) //设置宽高比 .setTargetRotation(Surface.ROTATION_0) // 设置旋转角度 .build(); cameraProvider.unbindAll(); Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner) activity, cameraSelector, imageCapture, preview, imageAnalysis); //这里previewView是预览图层,需要在布局中实现,然后在这里使用 preview.setSurfaceProvider(previewView.createSurfaceProvider(camera.getCameraInfo())); }
PreviewView的使用
<androidx.camera.view.PreviewView
android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
拍照回调有两种方式:
1.回调Image,需要保存的话,可以转Bitmap,然后保存
2.直接配置好保存路径,然后接收拍照成功和失败的回调
public void takePicture() { imageCapture.takePicture(executors, new ImageCapture.OnImageCapturedCallback() { @Override public void onCaptureSuccess(@NonNull ImageProxy imageProxy) { ImageProxy.PlaneProxy[] planes = imageProxy.getPlanes(); ByteBuffer buffer = planes[0].getBuffer(); buffer.position(0); byte[] bytes = new byte[buffer.capacity()]; buffer.get(bytes); imageProxy.close(); super.onCaptureSuccess(imageProxy); } }); /*ImageCapture.Metadata metadata = new ImageCapture.Metadata(); if (mCurrentCameraId == CameraSelector.LENS_FACING_FRONT) { metadata.setReversedHorizontal(true); } else { metadata.setReversedHorizontal(false); } File file = new File(Environment.getExternalStorageState(), new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US).format(System.currentTimeMillis()) + ".jpg"); ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions. Builder(file).setMetadata(metadata).build(); imageCapture.takePicture(outputFileOptions, executors, new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { Log.e(TAG, "outputFileResults:" + outputFileResults.getSavedUri()); } @Override public void onError(@NonNull ImageCaptureException exception) { Log.e(TAG, "exception:" + exception.toString()); } });*/ }
供应商扩展需要的同学可以自行在官网查看。
https://developer.android.google.cn/training/camerax
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。