java - 在不阻塞预览camera2 api的情况下从后台相机预览中捕获图片的可能方法?

标签 java android camera android-camera2

所以,事情是这样的。我试图在自动对焦锁定后立即从相机预览中获取照片。我现在能够做到这一点并且效果很好。现在,在捕获图片时,它会暂时阻止预览。我想在不妨碍预览的情况下完成整个捕获过程。有办法解决吗?

这是我当前的代码,它是基于 Google 示例相机 2 代码构建的。

         boolean areWeFocused = false;
                int counter =0;

                /**
                 * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture.
                 */
                private CameraCaptureSession.CaptureCallback mCaptureCallback
                        = new CameraCaptureSession.CaptureCallback() {

                    private void process(CaptureResult result) {
                        Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);

                        switch (mState) {
                            case STATE_PREVIEW: {
                                // We have nothing to do when the camera preview is working normally.
                                if (CaptureResult.CONTROL_AF_TRIGGER_START == afState) {
                                    if (areWeFocused) {
                                        //Run specific task here
                                        counter++;



                                        takePicture();
                                        Log.d("FocussedState","I am focussed now");
                                    }
                                }
                                if (CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState) {
                                    areWeFocused = true;
                                } else {
                                    areWeFocused = false;
                                    Log.d("FocussedState","I am not focussed now");

                                }
                                break;
                            }
        }
        private void takePicture() {
                lockFocus();
            }

            /**
             * Lock the focus as the first step for a still image capture.
             */
            private void lockFocus() {
                try {
                    // This is how to tell the camera to lock focus.
                    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                            CameraMetadata.CONTROL_AF_TRIGGER_START);
                    // Tell #mCaptureCallback to wait for the lock.
                    mState = STATE_WAITING_LOCK;
                    mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                            mBackgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
    private void captureStillPicture() {
            try {
                final Activity activity = getActivity();
                if (null == activity || null == mCameraDevice) {
                    return;
                }
                // This is the CaptureRequest.Builder that we use to take a picture.
                final CaptureRequest.Builder captureBuilder =
                        mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                captureBuilder.addTarget(mImageReader.getSurface());

                // Use the same AE and AF modes as the preview.
                captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                        CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
               // setAutoFlash(captureBuilder);

                // Orientation
                int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
                captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));

                CameraCaptureSession.CaptureCallback CaptureCallback
                        = new CameraCaptureSession.CaptureCallback() {

                    @Override
                    public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                                   @NonNull CaptureRequest request,
                                                   @NonNull TotalCaptureResult result) {
                        showToast("Saved: " + mFile);
                        Log.d(TAG, mFile.toString());
                        unlockFocus();
                    }
                };

                mCaptureSession.stopRepeating();
                mCaptureSession.abortCaptures();
                mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

  private ImageReader mImageReader;

    /**
     * This is the output file for our picture.
     */
    private File mFile;

    /**
     * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
     * still image is ready to be saved.
     */
    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
            = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
            mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
        }

    };

  private static class ImageSaver implements Runnable {

        /**
         * The JPEG image
         */
        private final Image mImage;
        /**
         * The file we save the image into.
         */
        private final File mFile;

        ImageSaver(Image image, File file) {
            mImage = image;
            mFile = file;
        }

        @Override
        public void run() {
            ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            FileOutputStream output = null;
            try {
                output = new FileOutputStream(mFile);
                output.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                mImage.close();
                if (null != output) {
                    try {
                        output.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

    /**
     * Compares two {@code Size}s based on their areas.
     */
    static class CompareSizesByArea implements Comparator<Size> {

        @Override
        public int compare(Size lhs, Size rhs) {
            // We cast here to ensure the multiplications won't overflow
            return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
                    (long) rhs.getWidth() * rhs.getHeight());
        }

    }

最佳答案

尝试删除 captureStillPicture 末尾的“mCaptureSession.stopRepeating()”和“abortCaptures”。

这些会阻止预览运行,直到重新启动为止,并且中止可能会导致输出出现故障。不过,它可以稍微加快捕捉时间,这可能就是它在那里的原因。

关于java - 在不阻塞预览camera2 api的情况下从后台相机预览中捕获图片的可能方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48189281/

相关文章:

java - ADF 审核日志记录

java - 触摸事件无法正常工作..libgdx

android - 我应该在 ViewModel 中包含 LifecycleOwner 吗?

unity-game-engine - 统一使用佳能或第三方数码相机作为 AR 相机选项

javascript - ThreeJS改变Camera的旋转焦点

java - 使用条件表达式尝试资源

java - 如何在 Java 中定位 JLabel 并调整其大小?

java - 无法在 Eclipse 中从 wsdl 和 xsd 文件生成 java 文件

android - 如果没有 GoogleCredential.Builder,GoogleCredential 将无法构建

c++ - 在 OpenCV 中使用自定义相机(通过 GStreamer)