Image Capturing with the Camera

You can capture still images with the device’s internal camera and keep images on your target device using the Camera API (in mobile and wearable applications). The main features of the Camera API include:

  • Previewing images in real time
  • Capturing and saving images
  • Controlling the camera settings, such as contrast, exposure, brightness, ISO, flash, white balance, and HDR

You can take photos using the Camera API through the following steps:

  1. Initialize the camera.
  2. Configure the camera.
  3. Preview and capture images.
  4. Terminate the camera.

The following figure illustrates the camera state changes in the normal mode.

Figure: Camera state changes

Camera state changes

Initializing the Camera

To initialize the camera, create a handle for the camera, configure the camera settings, and register callback functions for the events of preview and auto-focus:

  1. To use the functions and data types of the Camera API (in mobile and wearable applications), include the <camera.h> header file in your application:

    #include <camera.h>
    
  2. Create the camera handle using the camera_create() function.

    In the following example, create a g_camera camera handle, and define a camdata structure type, to store global data related to the camera handle:

    struct _camdata {
        Evas_Object *win;
        Evas_Object *rect;
        Evas *evas;
        camera_h g_camera; /* Camera handle */
    };
    typedef struct _camdata camdata;
    
    static camdata cam_data;
    
    int error_code = 0;
    
    /* Create the camera handle */
    error_code = camera_create(CAMERA_DEVICE_CAMERA0, &cam_data.g_camera);
    if (error_code != CAMERA_ERROR_NONE)
        dlog_print(DLOG_INFO, LOG_TAG, "fail to create camera: error code = %d", error_code);
    

    The CAMERA_DEVICE_CAMERA0 parameter means that the currently activated device camera is 0, which is the primary camera. You can select between the primary (0) and the secondary (1) camera, which are defined in the camera_device_e enumeration (in mobile and wearable applications). Since devices can have multiple camera sensors with different capabilities, you must create a camera handle with a proper camera_device_e value, determining which camera sensor is used. Usually, the primary sensor is located on the back side and the secondary sensor is on the front side of the device.

  3. Configure the camera settings.

    Before configuring the camera settings, find out which configurations are supported by the camera. Depending on the camera type, the device can support different orientations, resolutions, or preview and capture formats. You can obtain this information using the relevant functions, such as camera_foreach_supported_preview_resolution(), camera_foreach_supported_preview_format(), or other camera_foreach_supported_XXX() functions. For example, using the camera_foreach_supported_preview_resolution() function, you can find out which resolutions are supported for the camera preview on a specific device. As usual, the foreach function invokes a callback for each supported resolution and stops when the callback returns false.

    Set the camera configurations (such as image quality, display type, preview resolution, and capture format) by using the relevant functions:

    • Image quality

      Set the image quality using the camera_attr_set_image_quality() function. The quality value ranges from 1 (lowest quality) to 100 (highest quality).

      error_code = camera_attr_set_image_quality(cam_data.g_camera, 100);
      
    • Display type

      Using the camera_set_display() function, you can set the display type for showing preview images. The display type is either CAMERA_DISPLAY_TYPE_EVAS or CAMERA_DISPLAY_TYPE_OVERLAY.

      The following example shows how to set the display according to the display_type parameter:

      Note
      The camera state must be CAMERA_STATE_CREATED and the create_base_gui() function must be called before previewing.

      int error_code = CAMERA_ERROR_NONE;
      Evas_Object *g_eo = NULL;
      
      static void
      create_base_gui(camdata *cam_data, camera_display_type_e display_type)
      {
          /* Window */
          elm_config_accel_preference_set("opengl");
          /* PACKAGE contains the package name character info */
          cam_data->win = elm_win_add(NULL, PACKAGE, ELM_WIN_BASIC);
      
          evas_object_resize(cam_data->win, 240, 320);
      
          evas_object_move(cam_data->win, 0, 0);
          elm_win_autodel_set(cam_data->win, EINA_TRUE);
      
          cam_data->evas = evas_object_evas_get(cam_data->win);
      
          switch (display_type) {
          case CAMERA_DISPLAY_TYPE_EVAS:
              /* Set the Evas image object for drawing */
              g_eo = evas_object_image_add(cam_data->evas);
              evas_object_image_size_set(g_eo, 240, 320);
              evas_object_image_fill_set(g_eo, 0, 0, 240, 320);
              evas_object_resize(g_eo, 240, 320);
              evas_object_show(g_eo);
              evas_object_show(cam_data.win);
              break;
          case CAMERA_DISPLAY_TYPE_OVERLAY:
              cam_data->rect = evas_object_rectangle_add(cam_data->evas);
              evas_object_resize(cam_data->rect, 240, 320);
              evas_object_move(cam_data->rect, 0, 0);
              evas_object_color_set(cam_data->rect, 0, 0, 0, 0);
              evas_object_render_op_set(cam_data->rect, EVAS_RENDER_COPY);
              evas_object_size_hint_weight_set(cam_data->rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              /* Show the window after the base GUI is set up */
              evas_object_show(cam_data->win);
              break;
          case default:
          break;
          }
      }
      
      error_code = camera_set_display(cam_data.g_camera, CAMERA_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(cam_data.win));
      if (error_code != CAMERA_ERROR_NONE) {
          dlog_print(DLOG_DEBUG, "camera_set_display failed [0x%x]", ret);
          camera_destroy(cam_data.g_camera);
          cam_data.g_camera = 0;
      
          return;
      }
      
    • Preview resolution

      Set the preview resolution by calling the camera_set_preview_resolution() function before previewing.

      The following example code sets the camera preview resolution to the first found supported resolution, which is returned from the camera_foreach_supported_preview_resolution() function:

      int resolution[2];
      
      static bool
      _preview_resolution_cb(int width, int height, void *user_data)
      {
          int *resolution = (int*)user_data;
          resolution[0] = width;
          resolution[1] = height;
      
          return false;
      }
      
      /* Find a resolution that is supported by the device */
      error_code = camera_foreach_supported_preview_resolution(cam_data.g_camera, _preview_resolution_cb, resolution);
      
      /* Set the supported resolution for camera preview */
      error_code = camera_set_preview_resolution(cam_data.g_camera, resolution[0], resolution[1]);
      
    • Capture format

      Using the camera_set_capture_format() function, set the capture format. The available formats are defined in the camera_pixel_format_e enumeration (in mobile and wearable applications), such as NV12, NV16, and JPEG.

      error_code = camera_set_capture_format(cam_data.g_camera, CAMERA_PIXEL_FORMAT_JPEG);
      
  4. Register callback functions.

    To retrieve notifications, you must register appropriate callback functions for handling newly previewed frames and auto-focus state changes:

    • Camera preview

      To receive notifications about newly previewed frames, register a callback function using the camera_set_preview_cb() function. The callback is invoked once per frame during a preview.

      The following example implements the _camera_preview_cb() callback, which starts auto-focusing using the camera_start_focusing() function:

      error_code = camera_set_preview_cb(cam_data.g_camera, _camera_preview_cb, NULL);
      
      static void
      _camera_preview_cb(camera_preview_data_s *frame, void *user_data)
      {
          int error_code = 0;
      
          if (g_enable_focus == true) {
              error_code = camera_start_focusing(cam_data.g_camera, true);
      
              if (error_code == CAMERA_ERROR_NOT_SUPPORTED)
                  error_code = camera_start_focusing(cam_data.g_camera, false);
      
              g_enable_focus = false;
          }
      }
      

      The second parameter of the camera_start_focusing() function is a Boolean flag defining whether the camera must continuously maintain focus. The g_enable_focus flag is set to true at the application startup. For the first frame of the preview, the camera starts auto-focusing. Subsequent calls to the callback do not provoke any action, which prevents the auto-focusing process from starting after the first previewed frame.

    • Auto-focus state change

      Before auto-focusing starts, the auto-focus state is CAMERA_FOCUS_STATE_RELEASED. After the camera_start_focusing() function is called, the camera starts auto-focusing and the state changes to CAMERA_FOCUS_STATE_ONGOING. If the auto-focusing finishes successfully, the state changes to CAMERA_FOCUS_STATE_FOCUSED. If the auto-focusing fails, the state changes to CAMERA_FOCUS_STATE_FAILED.

      To receive notifications about auto-focusing state changes, register a callback using the camera_set_focus_changed_cb() function. The callback is invoked every time the auto-focus state changes.

      The following example implements the _camera_focus_cb() callback, which starts capturing focused frames using the camera_start_capture() function:

      static void
      _camera_focus_cb(camera_focus_state_e state, void *user_data)
      {
          int error_code;
      
          if (state == CAMERA_FOCUS_STATE_FOCUSED && g_enable_shot == true) {
              /*  Start capturing */
              error_code = camera_start_capture(cam_data.g_camera, _camera_capturing_cb, _camera_completed_cb, NULL);
      
              g_enable_shot = false;
          }
      }
      

Previewing and Capturing Images

After initializing the camera, you can start the preview, auto-focus, and capturing processes to take a photo. The camera preview starts with the camera_start_preview() function call, and it draws frames on the screen and allows you to capture frames as still images:

error_code = camera_start_preview(cam_data.g_camera);

After starting the camera preview, the image capturing flows as follows:

  1. To handle the camera preview, the application calls the camera preview callback, which calls the camera_start_focusing() function starting the auto-focusing process.
  2. To handle the auto-focusing process, the application calls the camera auto-focus callback, which calls the camera_start_capture() function starting the capturing process.
  3. To handle the capturing process, the application calls the camera capturing callback, which is invoked once for each captured frame.

The following example code implements the _camera_capturing_cb() callback, which saves the captured frame as a JPEG image, whose format is set by the camera_set_capture_format() function:

static void
_camera_capturing_cb(camera_image_data_s* image, camera_image_data_s* postview, camera_image_data_s* thumbnail, void *user_data)
{
    dlog_print(DLOG_DEBUG, LOG_TAG, "Writing image to file");
    FILE *file = fopen(g_fname, "w+");

    if (image->data != NULL)
        fwrite(image->data, 1, image->size, file);

    fclose(file);
}

You can get a notification when the image has been captured. After the camera_capturing_cb() function completes, the callback function, camera_capture_completed_cb(), is invoked. It is used for notification and for restarting the camera preview.

The following example code implements the _camera_completed_cb() callback, which waits 0.025 seconds before restarting the camera preview with auto-focusing. By waiting 0.025 seconds, the callback keeps the captured image on the screen for 0.025 seconds.

static void
_camera_completed_cb(void *user_data)
{
    int error_code = 0;

    usleep(25000);  /* Display the captured image for 0.025 seconds */

    /* Restart the camera preview */
    error_code = camera_start_preview(cam_data.g_camera);

    g_enable_focus = true;
}

Stopping the Camera

After you have finished working with the camera, you need to stop the camera and clean up the application environment:

  1. If auto-focus is switched on, switch it off using the camera_cancel_focusing() function.
  2. Stop the camera preview using the camera_stop_preview() function.
  3. Unregister the camera preview and auto-focus callback functions using the camera_unset_preview_cb() and camera_unset_focus_changed_cb() functions.
  4. Destroy the camera handle and release all the allocated resources using the camera_destroy() function.
error_code = camera_stop_preview(cam_data.g_camera);
error_code = camera_destroy(cam_data.g_camera);

if (error_code != CAMERA_ERROR_NONE)
    dlog_print(DLOG_INFO, LOG_TAG, "fail to destroy camera: error code = %d", error_code);