CameraX拍照(二)

根据官方文档学习CameraX的基础拍照功能


前言

记录使用Camera X时的用例

  • 预览
  • 图片拍摄
  • 图片分析
  • 视频拍摄

一、实现预览

在向应用添加预览时,请使用 PreviewView,这是一种可以剪裁、缩放和旋转以确保正确显示的 View

当相机处于活动状态时,图片预览会流式传输到 PreviewView 中的 Surface。

1.使用 PreviewView

使用 PreviewView 实现 CameraX 预览,请按以下步骤操作

  1. 可选)配置 CameraXConfig.Provider
  2. 将 PreviewView 添加到布局
  3. 请求 ProcessCameraProvider
  4. 在创建 View 时,请检查 ProcessCameraProvider
  5. 选择相机并绑定生命周期和用例

tips:使用 PreviewView 存在一些限制。使用 PreviewView 时,您无法执行以下任何操作:

  • 创建 SurfaceTexture,以在 TextureView 和 Preview.SurfaceProvider 上进行设置。
  • 从 TextureView 检索 SurfaceTexture,并在 Preview.SurfaceProvider 上对其进行设置。
  • 从 SurfaceView 获取 Surface,并在 Preview.SurfaceProvider 上对其进行设置。

如果出现上述任何一种情况,Preview 就会停止将帧流式传输到 PreviewView

下面根据步骤实现预览功能,代码如下:

1.将 PreviewView 添加到布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.camera.view.PreviewView
        android:id="@+id/previewView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

代码中有注释 ,就这样简单实现预览的功能:

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        //1.请求 CameraProvider
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        //2.检查 CameraProvider 可用性
        cameraProviderFuture.addListener(Runnable {
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(this))
    }

    /**
     * 选择相机并绑定生命周期和用例
     */
    private fun bindPreview(cameraProvider: ProcessCameraProvider) {
        //创建 Preview
        var preview: Preview = Preview.Builder().build()
        //指定所需的相机 LensFacing 选项
        var cameraSelector: CameraSelector = CameraSelector.Builder().requireLensFacing(
            CameraSelector.LENS_FACING_BACK
        ).build()
        //将所选相机和任意用例绑定到生命周期。
        preview.setSurfaceProvider(binding.previewView.surfaceProvider)
        //将 Preview 连接到 PreviewView。并返回一个Camera对象
        var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
    }

}

二、图片拍摄

  • 相机手动控制功能
  • 自动白平衡
  • 自动曝光
  • 自动对焦 (3A) 功能

调用方负责决定如何使用拍摄的照片,具体包括以下选项:

运行 ImageCapture 的可自定义执行程序有两种类型:回调执行程序和 IO 执行程序。

  • 回调执行程序是 takePicture 方法的参数。它用于执行用户提供的 OnImageCapturedCallback()
  • 如果调用方选择将图片保存到文件位置,您可以指定执行程序以执行 IO。如需设置 IO 执行程序,请调用 ImageCapture.Builder.setIoExecutor(Executor)。如果执行程序不存在,则默认 CameraX 为任务的内部 IO 执行程序。

1.拍照

代码如下(示例):

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
    private var imageCapture: ImageCapture? = null
    private lateinit var cameraExecutor: ExecutorService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        cameraExecutor = Executors.newSingleThreadExecutor()

        //1.请求 CameraProvider
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        //2.检查 CameraProvider 可用性
        cameraProviderFuture.addListener(Runnable {
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(this))
        binding.cameraCaptureButton.setOnClickListener {
            val name = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.CHINA)
                .format(System.currentTimeMillis())
            val contentValues = ContentValues().apply {
                put(MediaStore.MediaColumns.DISPLAY_NAME, name)
                put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
                    val appName = "app-name"
                    put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/${appName}")
                }
            }

            val outputOptions = ImageCapture.OutputFileOptions.Builder(
                contentResolver,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                contentValues
            ).build()

            imageCapture?.takePicture(outputOptions, cameraExecutor,
                object : ImageCapture.OnImageSavedCallback {
                    override fun onError(error: ImageCaptureException) {
                        // insert your code here.
                        Log.e("onError: ", "onError")
                    }

                    override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                        // insert your code here.
                        Log.e( "onImageSaved: ", "onImageSaved")
                    }
                })
        }

    }

    /**
     * 选择相机并绑定生命周期和用例
     */
    private fun bindPreview(cameraProvider: ProcessCameraProvider) {
        //创建 Preview
        var preview: Preview = Preview.Builder().build()
        //指定所需的相机 LensFacing 选项
        var cameraSelector: CameraSelector = CameraSelector.Builder().requireLensFacing(
            CameraSelector.LENS_FACING_BACK
        ).build()
        preview.setSurfaceProvider(binding.previewView.surfaceProvider)
        imageCapture = ImageCapture.Builder()
            .setTargetRotation(binding.previewView.display.rotation)
            .build()
        val imageAnalyzer = ImageAnalysis.Builder().build()
        //将所选相机和任意用例绑定到生命周期。
        cameraProvider.bindToLifecycle(
            this as LifecycleOwner,
            cameraSelector,
            imageCapture,
            imageAnalyzer,
            preview
        )
    }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Camerax是Android相机框架的一部分,它提供了便捷的API来实现相机预览和拍照功能。 要使用Camerax进行预览拍照,我们首先需要配置相机权限。在AndroidManifest.xml文件中,添加以下权限: ``` <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 接下来,在activity的布局文件中添加一个预览用的TextureView: ``` <TextureView android:id="@+id/previewView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 在相关的Activity中,我们使用Camerax来实现预览和拍照功能。首先,在onCreate方法中初始化Camerax的实例: ``` PreviewConfig previewConfig = new PreviewConfig.Builder().build(); Preview preview = new Preview(previewConfig); ImageCaptureConfig captureConfig = new ImageCaptureConfig.Builder().build(); ImageCapture imageCapture = new ImageCapture(captureConfig); CameraX.bindToLifecycle(this, preview, imageCapture); ``` 然后,我们需要将预览显示在TextureView中: ``` TextureView previewView = findViewById(R.id.previewView); preview.setSurfaceProvider(previewView.getSurfaceProvider()); ``` 最后,我们可以在需要的时候进行拍照: ``` // 通过点击按钮触发拍照 Button captureButton = findViewById(R.id.captureButton); captureButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "IMG_" + System.currentTimeMillis() + ".jpg"); ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build(); imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(MainActivity.this), new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { // 在此处对拍照后的图片进行处理 } @Override public void onError(@NonNull ImageCaptureException exception) { // 拍照出现错误时的处理 } }); } }); ``` 通过以上步骤,我们就可以使用Camerax来实现Android相机的预览和拍照功能。它提供了简单而强大的API,使得实现相机应用变得更加容易。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值