Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现摄像头的预览拍照+解决摄像头接线错误造成的显示问题 #152

Open
soapgu opened this issue Jul 12, 2022 · 0 comments
Labels
problem problem or trouble 安卓 安卓

Comments

@soapgu
Copy link
Owner

soapgu commented Jul 12, 2022

  • 前言

本篇重点是解决摄像头预览显示问题,顺便过一下androidx.camera的库预览的主要用法

  • androidx实现摄像头预览

本篇的实现基于

app.gradle部分
在dependencies增加

    def camerax_version = "1.1.0-alpha06"
    // CameraX core library using camera2 implementation
    implementation "androidx.camera:camera-camera2:$camerax_version"
    // CameraX Lifecycle Library
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    // CameraX View class
    implementation "androidx.camera:camera-view:1.0.0-alpha26"

界面层需要增加PreviewView控件

<androidx.camera.view.PreviewView
        android:id="@+id/preview_video_recode"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/button_photo"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

接下来是代码逻辑

  1. 检查确保Manifest.permission.CAMERA权限,在manifest里面增加
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.any" />
 注:预览拍照这些权限足够了
  1. 初始化操作
@SuppressLint("RestrictedApi")
    private void initCamera() {
        mCameraFuture = ProcessCameraProvider.getInstance(this);
        mCameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA;
        mPreview = new Preview.Builder()
                .build();
        mPreview.setSurfaceProvider(mPreviewView.getSurfaceProvider());

        /*
        mVideoCapture = new VideoCapture.Builder()
                .build();
         */
        imageCapture =
                new ImageCapture.Builder()
                        .setCaptureMode( ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY )
                        .build();

        try {
            mCameraProvider = mCameraFuture.get();
        } catch (ExecutionException | InterruptedException e) {
            Logger.e("初始化摄像头失败,%s", e.toString());
        }
    }

需要初始化

  • Preview:通过Preview.Builder实现,同时需要设置setSurfaceProvider,把UI控件PreviewView传入
  • ImageCapture:照相功能需要的对象,通过ImageCapture.Builder创建
  • VideoCapture.Builder可以录像,这里不需要所以注销了代码
  • 核心对象CameraProvider初始化
  1. 开始预览
 private void startPreview() {
        mCameraFuture.addListener(() -> {
            try {
                mCameraProvider.unbindAll();
                mCameraProvider.bindToLifecycle((LifecycleOwner) this,mCameraSelector,mPreview,imageCapture );
            } catch (Exception e) {
                Logger.e("预览摄像头失败,%s", e.toString());
            }
        }, ContextCompat.getMainExecutor(this) );
    }

其中,mPreview,imageCapture 都是可变参数,我这里只实现了预览和拍照所以只有两个参数,也可以实现录像等其他功能。

  1. 拍照
photoButton.setOnClickListener( v->{
           String dirPath = this.getExternalFilesDir("").getAbsolutePath();
           File dirFile = new File(dirPath);
           File file = new File(dirFile, System.currentTimeMillis() + ".jpg");
           ImageCapture.OutputFileOptions outputFileOptions =
                   new ImageCapture.OutputFileOptions.Builder(file).build();
           imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
               @Override
               public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                   Uri uri = outputFileResults.getSavedUri();
                   Logger.i( "Save photo:%s",uri );
               }

               @Override
               public void onError(@NonNull ImageCaptureException exception) {
                   Logger.e( exception, "save photo error" );
               }
           });
       } );

通过takePicture方法以及OnImageSavedCallback完成拍照以及图片处理逻辑

  • 接错摄像头的预览处理

前面的代码跑在一个任何一个安卓手机上都是没事的。因为手机一般不会把线接错。
但是我就碰到其他设备厂商把前置、后置摄像头给接错了
我不得不选中CameraSelector.DEFAULT_BACK_CAMERA这个参数但是实际是前置摄像头。

于是预览成了酱紫
图片
这不是软件的错,是接线的错。明明是后置的摄像头,接了前置的位置,呈现直接全部翻转了

为了扭转过来

mPreview = new Preview.Builder()
                .setTargetRotation(Surface.ROTATION_180)
                .build();

Preview这样生成,转180度成了这样
图片

  • 解决镜像问题
    上下颠倒是解决了,但是预览不是镜子的效果,我往左转,预览是往右,非常的难受。
    也比较好理解,我程序指定的是后置摄像头,它自然不会认为需要镜像。怎么解决那
    “眼睛”已经没办法动了,接都接好了,要再改就麻烦了。那我把成像再翻转下。
 mPreviewView.setScaleX(-1F);

总算搞定了。下次厂商再把摄像头接错也不怕了,你不改我改总行了吧。
这翻来覆去的,调得头都晕死了
图片

当然得加钱,开开玩笑哈
图片

@soapgu soapgu added 安卓 安卓 problem problem or trouble labels Jul 12, 2022
@soapgu soapgu changed the title 实现摄像头的预览+解决摄像头接线错误造成的显示问题 实现摄像头的预览拍照+解决摄像头接线错误造成的显示问题 Jul 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
problem problem or trouble 安卓 安卓
Projects
None yet
Development

No branches or pull requests

1 participant