android android-camera android-5.0-lollipop android-hardware

¿Cómo obtener un solo fotograma de vista previa en Camera2 API Android 5.0?



android-camera android-5.0-lollipop (2)

Un poco tarde pero mejor que nunca:

Por lo general, un TextureView se utiliza para mostrar la vista previa de la cámara. Puede utilizar TextureView.SurfaceTextureListener para obtener una devolución de llamada cada vez que cambie la superficie. TextureView proporciona un método getBitmap(Bitmap) que puede utilizar para obtener el marco de vista previa en el mismo tamaño que TextureView .

Puede utilizar esta muestra de Google como punto de partida. Simplemente actualice el surfaceTextureListener como se muestra aquí:

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 } }

Estoy tratando de obtener un marco de vista previa para la funcionalidad de escaneo de códigos QR utilizando la API de Camera2 . En la antigua API de la cámara es tan fácil como:

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 } });

Sin embargo, no puedo encontrar una manera de lograr eso usando la nueva API de Camera2. Me gustaría recibir varios marcos en los que puedo trabajar; lo mejor sería recibir la matriz de bytes como en la API antigua. ¿Alguna idea de cómo hacer eso?


Utilice el código de abajo para hacerlo.

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(); }