android video app still capture session

The android video app still capture session tutorial describes the setup of the camera capture session for capturing  a still image once the autofocus has locked.

Get Code

The code to start this tutorial is on github here

https://github.com/mobapptuts/android_camera2_api_video_app.git Tag camera2-video-still-preview

or you can run this command

git clone https://github.com/mobapptuts/android_camera2_api_video_app.git –branch camera2-video-still-preview

Steps

Add members for the image folder and image filenames

private File mImageFolder;
private static String mImageFileName;

 Create the image folder and call it from the onCreate method

private void createImageFolder() {
    File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    mImageFolder = new File(imageFile, "camera2VideoImage");
    if(!mImageFolder.exists()) {
        mImageFolder.mkdirs();
    }
}
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera2_video_image);

        createVideoFolder();
        createImageFolder();

 Add a method for creating unique file names for images

private File createImageFileName() throws IOException {
        String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
        String prepend = "IMAGE_" + timestamp + "_";
        File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder);
        mImageFileName = imageFile.getAbsolutePath();
        return imageFile;
    }

 Create a method to do the still capture in the preview session

 private void startStillCaptureRequest() {
        try {
            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            mCaptureRequestBuilder.addTarget(mImageReader.getSurface());
            mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, mTotalRotation);

            CameraCaptureSession.CaptureCallback stillCaptureCallback = new
                    CameraCaptureSession.CaptureCallback() {
                        @Override
                        public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) {
                            super.onCaptureStarted(session, request, timestamp, frameNumber);

                            try {
                                createImageFileName();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    };

            mPreviewCaptureSession.capture(mCaptureRequestBuilder.build(), stillCaptureCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

 Call that method inside the preview session callback

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

                private void process(CaptureResult captureResult) {
                    switch (mCaptureState) {
                        case STATE_PREVIEW:
                            // Do nothing
                            break;
                        case STATE_WAIT_LOCK:
                            mCaptureState = STATE_PREVIEW;
                            Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
                            if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
                                    afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
                                Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show();
                                startStillCaptureRequest();
                            }
                            break;
                    }
                }

                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                    super.onCaptureCompleted(session, request, result);

                    process(result);
                }
            };

 Create a runnable for saving the image to a file

private static class ImageSaver implements Runnable {

       private final Image mImage;

       private ImageSaver(Activity activity, Image image, Handler handler) {
           mImage = image;
       }

       @Override
       public void run() {
           ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
           byte[] bytes = new byte[byteBuffer.remaining()];
           byteBuffer.get(bytes);

           FileOutputStream fileOutputStream = null;

           try {
               fileOutputStream = new FileOutputStream(mImageFileName);
               fileOutputStream.write(bytes);
           } catch (IOException e) {
               e.printStackTrace();
           } finally {
               mImage.close();
               if(fileOutputStream != null) {
                   try {
                       fileOutputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }
       }
   }

Inside the ImageReader on image available listener to the image to the ImageSaver runnable so it can be saved to a file

private ImageReader.OnImageAvailableListener mImageAvailableListener = new
            ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    mBackgroundHandler.post(new ImageSaver(reader.acquireLatestImage()));
                }
            };

Now run the code in the application and see if it saves images while in the normal preview mode.

Android video app still capture session summary

In the android video app still capture session tutorial we had to setup the storage for the still images. Which involved creating a folder for the files and unique file names for each image.

We then created a capture request for the still images and used the onCaptureStarted callback to create the image filename.

We then created a runnable so that the image could be saved to storage with the assigned filename in a background thread. And then called the runnable once the capture still image was made available from the ImageReader.

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>