Camera: Controlling a Camera Device
This tutorial demonstrates how you can start a camera preview and take a photo. This tutorial also demonstrates how you can configure a camera by setting selected attributes.
Warm-up
Become familiar with the Camera API basics by learning about:
-
Initializing the Camera
Initialize the camera for use.
-
Taking a Photo
Start a camera preview and take a photo.
-
Setting Camera Attributes
Set the camera preview, zoom, and brightness attributes.
-
Releasing Resources
Stop the camera, unregister the callback functions, and destroy the camera handle and release all its resources.
Initializing the Camera
Before you can start a camera preview or take a photo:
-
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>
- Create a handle for the camera, and configure the camera.
- Register callback functions for handling the camera preview and camera auto-focus.
Creating and Configuring a Camera
-
Create a structure for storing the global data related to the camera handle. In this tutorial, the camdata structure is used to store the g_camera variable, which is the camera handle.
typedef struct _camdata { Evas_Object *win; Evas_Object *rect; Evas *evas; camera_h g_camera; // Camera handle } camdata; static camdata cam_data;
-
Create 2 auxiliary variables to control whether taking photos (g_enable_shot) and auto-focusing (g_enable_focus) are allowed. These variables are used in the _camera_preview_cb() and _camera_focus_cb() functions.
static bool g_enable_shot = false; static bool g_enable_focus = true;
-
Create a handle for the camera using the camera_create() function:
int error_code = 0; // Create 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 , "error code = %d", error_code); } else { dlog_print(DLOG_ERROR, LOG_TAG , "error code = %d", error_code); }
CAMERA_DEVICE_CAMERA0 means that the current activated camera sensor is 0, of 2 selectable devices. These values are defined in the camera_device_e enumeration (in mobile and wearable applications).
-
Check the current state of the camera using the camera_get_state() function:
camera_state_e state; // Check camera state after create error_code = camera_get_state(cam_data.g_camera, &state);
The returned state is one of the values defined in the camera_state_e enumeration (in mobile and wearable applications). If the state is not CAMERA_STATE_CREATED, reinitialize the camera.
-
Set the image quality using the camera_attr_set_image_quality() function:
error_code = camera_attr_set_image_quality(cam_data.g_camera, 100);
The supported quality of the image value's boundary is from 1 to 100.
-
Set the display for showing preview images by using the camera_set_display() function with 1 of the camera display types (CAMERA_DISPLAY_TYPE_EVAS or CAMERA_DISPLAY_TYPE_OVERLAY) defined in the camera_display_type_e enumeration (in mobile and wearable applications):
Note Depending on the device, the application must set the display preferences using the elm_config_accel_preference_set() function. - Example: Set the display according to the camera_display_type_e enumerator:
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's character info cam_data->win = elm_win_add(NULL, PACKAGE, ELM_WIN_BASIC); if (display_type == CAMERA_DISPLAY_TYPE_EVAS) { elm_win_title_set(cam_data->win, PACKAGE); elm_win_borderless_set(cam_data->win, EINA_TRUE); } evas_object_resize(cam_data->win, 240, 320); if (display_type == CAMERA_DISPLAY_TYPE_OVERLAY) { evas_object_move(cam_data->win, 0, 0); elm_win_autodel_set(cam_data->win, EINA_TRUE); } 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 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; }
This function must be called before previewing and thus the camera state must be CAMERA_STATE_CREATED.
- Example: Set the display according to the camera_display_type_e enumerator:
-
Set the camera preview resolution using the camera_set_preview_resolution() function (this function must be called before previewing).
To find out which resolutions can be set for the camera preview on a specific device, use the camera_foreach_supported_preview_resolution() function. It invokes a callback function for every supported preview resolution. Note that the foreach function stops when the callback function returns false.
The following example code sets the camera preview resolution to the first found supported resolution:
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 in 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]);
-
Set the capture format using the camera_set_capture_format() function:
error_code = camera_set_capture_format(cam_data.g_camera, CAMERA_PIXEL_FORMAT_JPEG);
The camera_pixel_format_e enumeration (in mobile and wearable applications) defines the available capture formats.
Setting Callbacks for Camera Preview and Camera Focus
-
To receive notifications about delivering a copy of the newly previewed frame, register a callback function using the camera_set_preview_cb() function. The callback function is called once per frame during the preview.
error_code = camera_set_preview_cb(cam_data.g_camera, _camera_preview_cb, NULL);
The following example code implements the _camera_preview_cb() callback function. The callback function starts auto-focusing using the camera_start_focusing() function, whose parameters are the camera_h camera handle and a Boolean flag defining whether the camera must continuously try to focus. The g_enable_focus flag is set to false to prevent the capturing process from restarting. If the result value of the camera_start_focusing() function with the continuous mode set to true is CAMERA_ERROR_NOT_SUPPORTED, set the second parameter value as false.
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 g_enable_focus flag is set to true at the application startup. When the callback is called for the first time (for the first frame of the given preview), the camera starts auto-focusing and the flag is set to false. No subsequent calls to the callback (for the remaining frames) take any action.
-
To receive notifications about auto-focus state changes, register a callback function using the camera_set_focus_changed_cb() function:
error_code = camera_set_focus_changed_cb(cam_data.g_camera, _camera_focus_cb, NULL);
After the camera_start_focusing() function is called, the camera starts auto-focusing. Before the auto-focus starts, the focus state is CAMERA_FOCUS_STATE_RELEASED. When the auto-focus starts, the state changes to CAMERA_FOCUS_STATE_ONGOING. If the process finishes successfully, the state changes to CAMERA_FOCUS_STATE_FOCUSED. If there are errors, the state changes to CAMERA_FOCUS_STATE_FAILED.
The following example code implements the _camera_focus_cb() callback function, which is called whenever the auto-focus state changes. The callback function starts the capture process if the camera is in the CAMERA_FOCUS_STATE_FOCUSED state and the g_enable_shot flag is true. The g_enable_shot flag is set to false to prevent the capturing process from restarting.
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 capture error_code = camera_start_capture(cam_data.g_camera, _camera_capturing_cb, _camera_completed_cb, NULL); g_enable_shot = false; } }
Taking a Photo
To take a photo:
- Initialize the camera.
- Start the camera preview.
The camera preview draws preview frames on the screen and allows you to capture frames as still images.
To start the camera preview, use the camera_start_preview() function:
error_code = camera_start_preview(cam_data.g_camera);
- Capture an image:
-
When the camera preview starts, the application calls the camera preview callback function (see Setting Callbacks for Camera Preview and Changing Focus). The callback function then calls the camera_start_focusing() function.
-
When the camera auto-focusing starts, the application calls the camera focus callback function (see Setting Callbacks for Camera Preview and Changing Focus). The callback function then calls the camera_start_capture() function, which starts capturing still images.
The following example code implements the _camera_capturing_cb() callback function. The callback function is called once for each captured frame and is used to get information about the captured image. The image is saved in the format set by the camera_set_capture_format() function (see Creating and Configuring a Camera). In this example, the format is JPEG.
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); }
-
The following example code implements the _camera_completed_cb() function. The callback function is used to provide a notification after capturing is finished. In this example, the application waits 0.025 seconds before restarting the camera preview with auto-focusing.
static void _camera_completed_cb(void *user_data) { int error_code = 0; usleep(25000); // Wait 0.025 seconds to show captured image // Start camera preview error_code = camera_start_preview(cam_data.g_camera); g_enable_focus = true; }
-
Setting Camera Attributes
You can set the following additional camera attributes:
- Camera preview attributes
- Camera zoom attribute
- Camera brightness attribute
Setting the Camera Preview Attributes
The camera preview attributes are a group of attributes that you can set before starting the preview. The following example code sets the FPS and image quality attributes:
error_code = camera_attr_set_preview_fps(cam_data.g_camera, CAMERA_ATTR_FPS_AUTO); error_code = camera_attr_set_image_quality(cam_data.g_camera, 100);
Setting the Camera Zoom Attribute
To set the zoom level, use the camera_attr_set_zoom() function. To get the range of the available zoom level values, use the camera_attr_get_zoom_range() function.
The following example code sets the zoom level to minimum:
int min, max; error_code = camera_attr_get_zoom_range(cam_data.g_camera, &min, &max); error_code = camera_attr_set_zoom(cam_data.g_camera, min);
Setting the Camera Brightness Attribute
The current brightness level is stored in the global g_bright_level variable. To get the range of the available brightness level values, use the camera_attr_get_brightness_range() function:
int min, max; error_code = camera_attr_get_brightness_range(cam_data.g_camera, &min, &max);
To get the current brightness level, use the camera_attr_get_brightness() function:
static int g_bright_level; error_code = camera_attr_get_brightness(cam_data.g_camera, &g_bright_level);
To set a new brightness level, use the camera_attr_set_brightness() function:
if (g_bright_level >= LEVEL_UPPER_BOUND) { dlog_print(DLOG_DEBUG, LOG_TAG , "Brightness is set to maximum level"); g_bright_level = LEVEL_UPPER_BOUND - 1; } else if (g_bright_level <= LEVEL_LOWER_BOUND) { dlog_print(DLOG_DEBUG, LOG_TAG , "Brightness is set to maximum level"); g_bright_level = LEVEL_LOWER_BOUND + 1; } else { g_bright_level++; } // Set camera brightness error_code = camera_attr_set_brightness(cam_data.g_camera, g_bright_level);
Releasing Resources
After you have finished working with the camera, stop the camera and clean up the application environment:
- If the auto-focus is switched on, switch if off using the camera_cancel_focusing() function:
error_code = camera_cancel_focusing(cam_data.g_camera);
- Stop the camera preview using the camera_stop_preview() function:
error_code = camera_stop_preview(cam_data.g_camera);
- Unregister the camera preview and camera focus change callback functions using the camera_unset_preview_cb() and camera_unset_focus_changed_cb() functions, respectively:
// Unregister camera preview callback error_code = camera_unset_preview_cb(cam_data.g_camera); // Unregister camera focus change callback error_code = camera_unset_focus_changed_cb(cam_data.g_camera);
- Destroy the camera handle and release all its resources using the camera_destroy() function:
error_code = camera_destroy(cam_data.g_camera);