Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Taking a picture as fast as possible with Camera API on Android

Scenario:

I need to take a picture as fast as possible and save it to SD Card. It would be fantastic if I could do it in around 0.2 seconds both taking the picture and saving it.

What I did so far:

As normal I've created a SurfaceView to handle the Camera preview and initialized the camera object. The quality of the image doesn't need to be very high, that's why I am not using the largest resolution possible and also no autofocus is required. I set the parameters like this:

 Parameters parameters = camera.getParameters();
 parameters.set("jpeg-quality", 70);

 parameters.setPictureFormat(ImageFormat.JPEG);
 List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
 Size size = sizes.get(Integer.valueOf((sizes.size()-1)/2)); //choose a medium resolution
 parameters.setPictureSize(size.width, size.height);
 camera.setParameters(parameters);
 camera.setDisplayOrientation(90);

 List<Size> sizes2 = parameters.getSupportedPreviewSizes();
 Size size2 = sizes.get(0);

 parameters.setPreviewSize(size2.width, size2.height);
 camera.setPreviewDisplay(holder);
 camera.startPreview();

I save the image to SD card very simple with:

PictureCallback handlePictureStorage = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            FileOutputStream outStream = null;

            try {
                outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
                outStream.write(data);
                outStream.close();       
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
        }
    };

After making a few tests, on my Galaxy Nexus, the result looks like:

  • Setting picture size to : wigth=1600 height=1200
  • Jpeg quality : 70, Picture format JPEG
  • Fire take picture at: 00:13:23.603
  • Start saving picture on SD Card at: 00:13:23.956
  • Finished saving picture on SD Card at: 00:13:23.990

This is almost 0.4 seconds. Is there a way to tweak the Camera parameters even more to gain some faster speed ? The resolution is OK, the quality of the picture also. I know that there are apps on market that have 30 pictures per second but I think they use buffering to achieve that speed. However, as you may see the biggest time is lost with taking the picture rather than saving it to card. It would be great if I could tweak this a bit more.

like image 638
Alin Avatar asked Aug 14 '12 16:08

Alin


People also ask

Does image capture work with Android?

Image Capture on your Mac The native app macOS app that works with a lot of third-party devices is Image Capture. Not only can you use it for your iPhone or DSLR camera, but you can also use a scanner with the app. That also means you can use it to import pictures from your Android too.

What is Camera2 API Android?

Camera2 is the latest low-level Android camera package and replaces the deprecated Camera class. Camera2 provides in-depth controls for complex use cases, but requires you to manage device-specific configurations. You can read about specific Camera2 classes and functions in the reference documentation.

How do I get my Android camera to take pictures?

This is done as follows: Intent camera_intent = new Intent(MediaStore. ACTION_IMAGE_CAPTURE); startActivityForResult(camera_intent, pic_id); Now use the onActivityResult() method to get the result, here is the captured image.


1 Answers

After I did a bit of testing with multiple parameters, conclusion is that not much is left to be done. Here are some parameters I've set:

  //set color efects to none
 cameraParameters.setColorEffect(Camera.Parameters.EFFECT_NONE);

  //set antibanding to none
 if (cameraParameters.getAntibanding() != null) {
 cameraParameters.setAntibanding(Camera.Parameters.ANTIBANDING_OFF);
 }

 // set white ballance
 if (cameraParameters.getWhiteBalance() != null) {
 cameraParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
 }

  //set flash
 if (cameraParameters.getFlashMode() != null) {
 cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
 }

  //set zoom
 if (cameraParameters.isZoomSupported()) {
 cameraParameters.setZoom(0);
 }

 //set focus mode
 cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);

However, the best idea is to get the full string list of parameters supported by the camera, and try to tweak them. To get the string, use the flatten method of Camera.Parameters - http://developer.android.com/reference/android/hardware/Camera.Parameters.html#flatten()

But in order to get images really quick, I had to use preview with buffer, and for each frame taken, try to save it on sd-card in a thread. The picture quality isn't fantastic, but it's a start.

like image 101
Alin Avatar answered Nov 15 '22 22:11

Alin