您的位置:首页 > 房产 > 建筑 > 陕西网站建设优化建站_美工培训班一般培训多久_搜狗网站排名软件_谷歌seo实战教程

陕西网站建设优化建站_美工培训班一般培训多久_搜狗网站排名软件_谷歌seo实战教程

2024/12/28 10:19:52 来源:https://blog.csdn.net/weixin_45407364/article/details/143178840  浏览:    关键词:陕西网站建设优化建站_美工培训班一般培训多久_搜狗网站排名软件_谷歌seo实战教程
陕西网站建设优化建站_美工培训班一般培训多久_搜狗网站排名软件_谷歌seo实战教程

Android 相机CameraX框架

CameraX是Jetpack 支持库,利用的是 camera2 的功能,它具有生命周期的感应,使用更加简单,代码量也减少了不少。可以灵活的录制视频和拍照
官方文档
https://developer.android.google.cn/media/camera/camerax?hl=ro
build.gradle的dependencies中引入框架

def cameraxVersion = "1.1.0-alpha05";
implementation "androidx.camera:camera-core:${cameraxVersion}"
implementation "androidx.camera:camera-camera2:${cameraxVersion}"
implementation "androidx.camera:camera-lifecycle:${cameraxVersion}"
//CameraX添加依赖
implementation "androidx.camera:camera-view:1.3.0-alpha07"
implementation 'androidx.camera:camera-video:'
implementation "androidx.lifecycle:lifecycle-common-java8:2.5.1"

配置CameraXConfig

使用 setAvailableCameraLimiter() 优化启动延迟时间。
使用 setCameraExecutor() 向 CameraX 提供应用执行器。
将默认调度器处理程序替换为 setSchedulerHandler()。
使用 setMinimumLoggingLevel() 更改日志记录级别。

图像预览PreviewView

选择相机并绑定生命周期和用例:
创建 Preview。
指定所需的相机 LensFacing 选项。
将所选相机和任意用例绑定到生命周期。
将 Preview 连接到 PreviewView。

    void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {Preview preview = new Preview.Builder().build();//设置缩放类型可选FIT_CENTER、FIT_START 和 FIT_END,默认缩放类型是 FILL_CENTER。preview .setScaleType(PreviewView.ScaleType.FIT_CENTER);CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();preview.setSurfaceProvider(previewView.getSurfaceProvider());Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview);
}

图像分析ImageAnalysis

设置图片输出尺寸,输出格式,旋转角度…
输出格式:CameraX 可通过 setOutputImageFormat(int) 支持 YUV_420_888 和 RGBA_8888。默认格式为 YUV_420_888。
注意:使用 ProcessCameraProvider.bindToLifecycle() 函数将 ImageAnalysis 绑定到现有的 AndroidX 生命周期

    imageAnalysis = ImageAnalysis.Builder().setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
//            .setTargetResolution(Size(1280, 720))设置实际的尺寸.setTargetAspectRatio(AspectRatio.RATIO_4_3) //设计宽高比.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888).build()//创建分析器imageAnalysis!!.setAnalyzer(cameraExecutor!!,ImageAnalysis.Analyzer { imageProxy: ImageProxy ->//通过调用 ImageProxy.close() 将 ImageProxy 发布到 CameraXimageProxy.close()})
...
cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);

图像拍摄输出保存

拍摄的配置参数,例如闪光灯、连续自动对焦、零快门延迟等。

        imageCapture = new ImageCapture.Builder()//控制闪光灯模式 FLASH_MODE_ON(拍照时,闪光灯会亮起), //FLASH_MODE_OFF 闪光灯关闭,FLASH_MODE_AUTO:在弱光环境下拍摄时,自动开启闪光灯。.setFlashMode(ImageCapture.FLASH_MODE_ON)//ImageCapture.Builder.setCaptureMode() 可用于配置拍摄照片时所采用的拍摄模式://CAPTURE_MODE_MINIMIZE_LATENCY:缩短图片拍摄的延迟时间。//CAPTURE_MODE_MAXIMIZE_QUALITY:提高图片拍摄的图片质量。.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).build();

拍照保存图片的方式有2种,
takePicture(OutputFileOptions, Executor, OnImageSavedCallback):此方法将拍摄的图片保存到提供的文件位置。

            val name = System.currentTimeMillis().toString() + ".jpg"val contentValues = ContentValues()contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name)contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH,FileUtils.getSystemPicDataPath() //图片路径)}//图片输出val outputFileOptions = OutputFileOptions.Builder(contentResolver,MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues).build()imageCapture!!.takePicture(outputFileOptions,ContextCompat.getMainExecutor(this),object : ImageCapture.OnImageSavedCallback {override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {//content://media/external/images/media/125//Pictures/CameraXImage//aaa图片路径.jpgprintLog(" aaa图片路径--" + FileUtils.getSystemPicDataPath() + name)CoroutineScope(Dispatchers.IO).launch {val blo = FileUtils.copyFile(FileUtils.getSystemPicDataPath() + name,FileUtils.getAppPicDataPath() + name)withContext(Dispatchers.Main) {printLog("文件复制成功$blo")if (blo) {File(FileUtils.getAppPicDataPath() + name).delete()binding.ivCamera.visibility = View.VISIBLEFileUtils.showGlidePic(this@CameraActivity,FileUtils.getAppPicDataPath() + name,binding.ivCamera)}}}//  printLog( Objects.requireNonNull(outputFileResults.savedUri).toString())}override fun onError(exception: ImageCaptureException) {printLog(exception.toString())}})

另一种takePicture(Executor, OnImageCapturedCallback):此方法为拍摄的图片提供内存缓冲区。

   imageCapture!!.takePicture(ContextCompat.getMainExecutor(this), object :ImageCapture.OnImageCapturedCallback() {override fun onCaptureSuccess(image: ImageProxy) {super.onCaptureSuccess(image)// println(image)// printLog("文件保存成功${image.format}")if (image.format === ImageFormat.JPEG) {val planes = image.planesval buffer = planes[0].bufferval size = buffer.remaining()val jpeg = ByteArray(size)buffer[jpeg, 0, size]val bitmap: Bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.size);val path=FileUtils.getAppPicDataPath() + name//将bitmap保存为图片val isFlag=FileUtils.bitmapToFile(bitmap,path)printLog("文件保存成功$isFlag")if (isFlag){binding.ivCamera.visibility = View.VISIBLE//存储图片成功,现实图片FileUtils.showGlidePic(this@CameraActivity,path,binding.ivCamera)}else{toast("获取图片失败")}}image.close()}override fun onError(exception: ImageCaptureException) {printLog(exception.toString())}})

完整代码演示:
xml文件自定义UI

<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".ui.activity.CameraVideo2Activity"><androidx.camera.view.PreviewViewandroid:id="@+id/preview_view"android:layout_width="match_parent"android:layout_height="match_parent" /><Buttonandroid:id="@+id/takeVideoBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="录像"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toStartOf="@id/takePhotoBtn"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias=".9" /><Buttonandroid:id="@+id/takePhotoBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="拍照"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toEndOf="@+id/takeVideoBtn"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias=".9" />
</androidx.constraintlayout.widget.ConstraintLayout>

activity代码

public class CameraVideo2Activity extends AppCompatActivity {//按钮Button takePhotoButton;Button takeVideoButton;//预览PreviewView previewView;//权限private static final String[] REQUIRE_PERMISSIONS = new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};public static final int REQUEST_CODE_PERMISSIONS = 10;//captureImageCapture imageCapture;ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;//录像VideoCapture videoCapture;Recording recording;//executor & imageAnalysisprivate ExecutorService cameraExecutor;private ImageAnalysis imageAnalysis;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_camera_video2);//绑定控件takePhotoButton = findViewById(R.id.takePhotoBtn);takeVideoButton = findViewById(R.id.takeVideoBtn);previewView = findViewById(R.id.preview_view);takePhotoButton.setOnClickListener(v -> takePhoto());takeVideoButton.setOnClickListener(v -> takeVideo());//获取权限if (havePermissions()) {initCamera();} else {ActivityCompat.requestPermissions(this, REQUIRE_PERMISSIONS, REQUEST_CODE_PERMISSIONS);}//executor实例cameraExecutor = Executors.newSingleThreadExecutor();}@Overrideprotected void onDestroy() {super.onDestroy();cameraExecutor.shutdown();}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_CODE_PERMISSIONS) {initCamera();} else {finish();}}//判断权限是否获取private boolean havePermissions() {for (String permission : REQUIRE_PERMISSIONS) {if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {return false;}}return true;}//初始化Camera@SuppressLint("UnsafeOptInUsageError")private void initCamera() {///实例化(可以设置许多属性)imageCapture = new ImageCapture.Builder()//控制闪光灯模式 FLASH_MODE_ON(拍照时,闪光灯会亮起), FLASH_MODE_OFF 闪光灯关闭.setFlashMode(ImageCapture.FLASH_MODE_ON).build();Recorder recorder = new Recorder.Builder().build();videoCapture = VideoCapture.withOutput(recorder);processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(this);processCameraProviderListenableFuture.addListener(() -> {try {//配置预览(https://developer.android.google.cn/training/camerax/preview?hl=zh-cn)previewView.setScaleType(PreviewView.ScaleType.FIT_CENTER);Preview preview = new Preview.Builder().build();preview.setSurfaceProvider(previewView.getSurfaceProvider());//绑定到生命周期ProcessCameraProvider processCameraProvider = processCameraProviderListenableFuture.get();//图片分析initImageAnalysis();//设置旋转setOrientationEventListener();//剪裁矩形(拍摄之后,对图片进行裁剪)ViewPort viewPort = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {viewPort = new ViewPort.Builder(new Rational(100, 100), getDisplay().getRotation()).build();} else {viewPort = new ViewPort.Builder(new Rational(100, 100), Surface.ROTATION_0).build();}UseCaseGroup useCaseGroup = new UseCaseGroup.Builder().addUseCase(preview).addUseCase(imageAnalysis).addUseCase(imageCapture).addUseCase(videoCapture).setViewPort(viewPort).build();processCameraProvider.unbindAll();Camera camera = processCameraProvider.bindToLifecycle(CameraVideo2Activity.this, CameraSelector.DEFAULT_BACK_CAMERA, useCaseGroup);//DEFAULT_BACK_CAMERA 后置摄像头//CameraCameraControl cameraControl = camera.getCameraControl();CameraInfo cameraInfo = camera.getCameraInfo();} catch (ExecutionException | InterruptedException e) {e.printStackTrace();}}, ContextCompat.getMainExecutor(this));}//图片分析@SuppressLint("UnsafeOptInUsageError")private void initImageAnalysis() {imageAnalysis = new ImageAnalysis.Builder().setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build();imageAnalysis.setAnalyzer(cameraExecutor, imageProxy -> {int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();imageProxy.close();});}///旋转//orientation为北为0,顺时针度数0-360//Surface.ROTATION_270将拍摄好的图片顺时针旋转270度private void setOrientationEventListener() {OrientationEventListener orientationEventListener = new OrientationEventListener(this) {@Overridepublic void onOrientationChanged(int orientation) {int rotation;if (orientation >= 45 && orientation < 135) {rotation = Surface.ROTATION_270;} else if (orientation >= 135 && orientation < 225) {rotation = Surface.ROTATION_180;} else if (orientation >= 225 && orientation < 315) {rotation = Surface.ROTATION_90;} else {rotation = Surface.ROTATION_0;}imageCapture.setTargetRotation(rotation);}};orientationEventListener.enable();}//拍照private void takePhoto() {if (imageCapture != null) {//ContentValuesString name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.SIMPLIFIED_CHINESE).format(System.currentTimeMillis());ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/CameraXImage");}//图片输出ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build();imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {@Overridepublic void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {//content://media/external/images/media/125//Pictures/CameraXImage//aaa图片路径5.jpgSystem.out.println("图片路径--"+name+".jpg");Log.i("camera", Objects.requireNonNull(outputFileResults.getSavedUri()).toString());}@Overridepublic void onError(@NonNull ImageCaptureException exception) {Log.e("camera", exception.toString());}});}}//录像private void takeVideo() {if (videoCapture != null) {takeVideoButton.setEnabled(false);if (recording != null) {recording.stop();recording = null;return;}String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.SIMPLIFIED_CHINESE).format(System.currentTimeMillis()) + ".mp4";ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "Movies/CameraX-Video");}MediaStoreOutputOptions mediaStoreOutputOptions = new MediaStoreOutputOptions.Builder(getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI).setContentValues(contentValues).build();Recorder recorder = (Recorder) videoCapture.getOutput();if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, REQUIRE_PERMISSIONS, REQUEST_CODE_PERMISSIONS);return;}recording = recorder.prepareRecording(this, mediaStoreOutputOptions).withAudioEnabled().start(ContextCompat.getMainExecutor(this), videoRecordEvent -> {if (videoRecordEvent instanceof VideoRecordEvent.Start) {takeVideoButton.setText("停止");takeVideoButton.setEnabled(true);} else if (videoRecordEvent instanceof VideoRecordEvent.Finalize) {if (((VideoRecordEvent.Finalize) videoRecordEvent).hasError()) {if (recording != null) {recording.close();recording = null;}} else {//视频为content://media/external/video/media/122//Movies/CameraX-Video/nameString msg = "视频为" + ((VideoRecordEvent.Finalize) videoRecordEvent).getOutputResults().getOutputUri();Log.i("camera", msg);Log.i("camera", "视频路径为"+name);}takeVideoButton.setEnabled(true);takeVideoButton.setText("录像");}});}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com