简体   繁体   English

Android CAMERA 2 API捕获0kb图像并提供全白预览。 在logcat上不显示任何错误或警告

[英]Android CAMERA 2 API captures 0kb images & gives a full white preview. Shows no errors or warnings on logcat

I use Android CAMERA 2 API for the camera2 supporting phones on my app. 我将Android CAMERA 2 API用于支持我的应用程序中的camera2支持的手机。 Works great, but some times it captures 0kb images & gives a full white preview . 效果很好,但有时会捕获0kb图像并提供全白预览 Shows no errors or warnings on logcat. 在logcat上不显示任何错误或警告。 Below is my camera image capture & save code: 以下是我的相机图像捕获和保存代码:

protected void takePictureViaCamera2() {
    if (null == cameraDevice) {
        Log.e(TAG, "cameraDevice is null");
        return;
    }
    CameraManager manager = (CameraManager) 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 = 640;
        int height = 480;
        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 = getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
        //final File file = new File(Environment.getExternalStorageDirectory()+"/pic.jpg");
        final File file = createImageFile();
        final String checkPath = file.getParent();
        Log.e("checkPath", checkPath);
        //photoFile = createImageFile();
        //photoFilePath  = photoFile.getParent();
        //Log.e("photoFilePath", photoFilePath);
        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();
                    Log.e("readerListenerFNF_EX", e + "");
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("readerListenerIO_EX", e + "");
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e("readerListener_EX", e + "");
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }

            private void save(byte[] bytes) throws IOException {
                OutputStream output = null;
                try {
                    output = new FileOutputStream(file);
                    //output = new FileOutputStream(photoFile);
                    output.write(bytes);
                } finally {
                    if (null != output) {
                        output.close();
                    }
                }
            }
        };
        reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
        final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                Toast.makeText(TravelChargesCamera2Activity.this, "Saved***:" + file, Toast.LENGTH_SHORT).show();
                createCameraPreview();
                closeCamera();


                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        try {
                            synchronized (this) {
                                wait(5000);

                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        toolbar.setVisibility(View.VISIBLE);
                                        header.setVisibility(View.VISIBLE);
                                        assessorTraveldetails_scroll.setVisibility(View.VISIBLE);
                                        camera2Layout.setVisibility(View.GONE);

                                        try {

                                            if (!file.getParentFile().isDirectory()) {

                                                travelDirectory = new File(checkPath);
                                                Log.e("travelDir==created==", travelDirectory + "");
                                            } else {

                                                travelDirectory = file.getParentFile();
                                                Log.e("travelDir==exists==", travelDirectory + "");
                                            }

                                            files = travelDirectory.listFiles();
                                            Log.e("files", files + "");

                                            // removes old images from view
                                            // prevents  display duplication
                                            travelGallery.removeAllViews();

                                            // loop displays the photos captured on Horizontal ScrollView
                                            for (File picFile : files) {
                                                travelGallery.addView(insertPhoto(picFile.getAbsolutePath()));

                                                byte[] byteArray = ImageUtils.fileToByteArray(file);
                                                Log.e("byteArray", byteArray + "");
                                            }

                                        } catch (Exception e) {
                                            e.printStackTrace();
                                            Log.e("file", e + "");
                                        }
                                    }
                                });

                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            Log.e("InterruptedException", e + "");
                        } catch (Exception e) {
                            e.printStackTrace();
                            Log.e("Exception", e + "");
                        }
                    }
                };
                thread.start();

            }
        };
        cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                try {
                    session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
            }
        }, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
        Log.e("CameraAccessException", e + "");
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("takePictureViaCamera2", e + "");
    }
}

private File createImageFile() throws IOException {
    // Create an image file name

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String uniqueId = UUID.randomUUID().toString();
    String imageFileName = "CAP_" + timeStamp + "_" + uniqueId;


    String bCode = "";

    masterMap = (LinkedTreeMap) gson.fromJson(batchMasterObject.getMasterJson(), Object.class);
    auditMap = (LinkedTreeMap) masterMap.get("2001");
    if ((auditMap.get("batchCode") != null && !auditMap.get("batchCode").equals(""))) {
        bCode = auditMap.get("batchCode").toString();
    } else if (auditMap.get("cbc") != null && !auditMap.get("cbc").equals("")) {
        bCode = auditMap.get("cbc").toString();
    }


    File storageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "/" + bCode + "/Travel/");

    if (!storageDir.exists()) {
        storageDir.mkdirs();
    }
    String checkPath = storageDir.getPath();
    Log.e("checkPath", checkPath);

    Toast.makeText(getApplicationContext(), checkPath, Toast.LENGTH_LONG).show();

    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents        
    mCurrentPhotoPath = storageDir.getAbsolutePath();
    return image;
}

Could any one help on this? 有人可以帮忙吗?

NOTE: The camera, captures and stores an image file as intended, but the file size is 0kb. 注意:相机会按预期捕获和存储图像文件,但是文件大小为0kb。 When the image file is opened on phone or pc, it says "Unsupported format" 在手机或PC上打开图片文件时,显示“不支持的格式”

It looks like you're taking your final JPEG capture as the very first frame. 好像您将最终的JPEG捕获作为第一帧。

This means the camera's auto-exposure routines have not had any time to work (since you're grabbing the first frame), so the image will be captured with the initial settings hardcoded into the camera driver. 这意味着相机的自动曝光例程没有任何时间可用(因为您正在抓取第一帧),因此将使用硬编码到相机驱动程序中的初始设置来捕获图像。 This may work for some scenes, but in others, the image will be far too bright or far too dark. 这可能适用于某些场景,但在另一些场景中,图像将太亮或太暗。

For best results, you should first let the camera meter for a while, until auto-exposure and auto-focus are converged. 为了获得最佳效果,您应该先让相机测光一会儿,直到自动曝光和自动对焦收敛为止。

Generally, this can be done by setting up a low-resolution preview output (use a SurfaceTexture for example), and running it for a second or two (or wait until a CaptureResult has an AE_STATE of CONVERGED). 通常,可以通过设置低分辨率预览输出(例如,使用SurfaceTexture)并运行一两秒(或等到CaptureResult的AE_STATE为CONVERGED来完成)。 Then issue the JPEG capture. 然后发出JPEG捕获。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM