web-dev-qa-db-fra.com

Comment obtenir un cadre de prévisualisation unique dans Camera2 API Android 5.0?

J'essaie d'obtenir un cadre d'aperç pour la fonctionnalité de numérisation de code QR en utilisant API Camera2. Dans l'ancienne API Camera, c'est aussi simple que:

    Android.hardware.Camera mCamera;
    ...
    mCamera.setPreviewCallback(new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            // will be invoked for every preview frame in addition to displaying them on the screen             
        }
    });

Cependant, je ne peux pas trouver un moyen d'y parvenir en utilisant nouvea API Camera2. J'aimerais recevoir plusieurs trames sur lesquelles je peux travailler - le mieux serait de recevoir un tableau d'octets comme dans l'ancienne API. Des idées pour faire ça?

21
theb1uro

Un peu tard mais mieux que jamais:

Habituellement, un TextureView est utilisé pour afficher l'aperçu de la caméra. Vous pouvez utiliser TextureView.SurfaceTextureListener Pour obtenir un rappel chaque fois que la surface change. TextureView fournit une méthode getBitmap(Bitmap) que vous pouvez utiliser pour obtenir le cadre de prévisualisation dans la même taille que le TextureView.

Vous pouvez utiliser cet exemple Google comme point de départ. Mettez simplement à jour la surfaceTextureListener comme indiqué ici:

private val surfaceTextureListener = object : TextureView.SurfaceTextureListener {

    override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) {
        openCamera(width, height)
    }

    override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {
        configureTransform(width, height)
    }

    override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) = true

    override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {
        // Start changes
        // Get the bitmap
        val frame = Bitmap.createBitmap(textureView.width, textureView.height, Bitmap.Config.ARGB_8888)
        textureView.getBitmap(frame)

        // Do whatever you like with the frame
        frameProcessor?.processFrame(frame)
        // End changes
    }

}
6
crysxd

Utilisez le code ci-dessous pour le faire.

 CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
            Size[] jpegSizes = null;
            if (characteristics != null) {
                jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
            }
            int width = 480;//480x320
            int height = 320;
            if (jpegSizes != null && 0 < jpegSizes.length) {
                width = jpegSizes[0].getWidth();
                height = jpegSizes[0].getHeight();
            }
            ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
            List<Surface> outputSurfaces = new ArrayList<Surface>(2);
            outputSurfaces.add(reader.getSurface());
            outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
            final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(reader.getSurface());
            captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
            // Orientation
            int rotation = ((Activity) context).getWindowManager().getDefaultDisplay().getRotation();
            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            final File file = getFileDir();
            ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    Image image = null;
                    try {
                        image = reader.acquireLatestImage();
                        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                        byte[] bytes = new byte[buffer.capacity()];
                        buffer.get(bytes);
                        save(bytes);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (image != null) {
                            image.close();
                        }
                    }
                }

                private void save(byte[] bytes) throws IOException {
                    OutputStream output = null;
                    try {
                        output = new FileOutputStream(file);
                        output.write(bytes);
                    } finally {
                        if (null != output) {
                            output.close();
                        }
                    }
                }
            };
            reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
1
Rohit Parmar