Media Vision: Generating and Detecting Barcodes
This tutorial demonstrates how you can generate and detect barcodes in the camera preview.
This feature is supported in mobile applications only.
Warm-up
Become familiar with the Media Vision API basics by learning about:
-
Initializing the Barcode Engines
Initialize the barcode generation and detection engines for use.
-
Generating Barcodes
Generate a barcode into memory or a file.
-
Detecting Barcodes
Detect barcodes in the camera preview.
Initializing the Barcode Engines
To initialize the barcode generation and detection engines for use:
-
To use the functions and data types of the Media Vision API, include the <mv_barcode.h> header file in your application:
#include <mv_barcode.h>
-
For barcode generation:
-
Create a structure for storing the data required for barcode generation engine configuration:
typedef struct _bargendata_s { // Barcode information variables mv_barcode_type_e type; mv_barcode_qr_ecc_e ecc; mv_barcode_qr_mode_e mode; int version; size_t width; size_t height; mv_barcode_image_format_e image_format; // Media source handle mv_source_h g_source; // Barcode generation engine handle mv_engine_config_h g_engine_cfg; } bargendata_s; static bargendata_s bargendata;
-
Configure the barcode generation engine using the mv_create_engine_config() function. The function configures the engine with default attribute values.
int error_code = 0; error_code = mv_create_engine_config(&bargendata.g_engine_cfg); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
For example, to define whether the barcode is generated with text, use the mv_engine_config_set_int_attribute() function with the MV_BARCODE_GENERATE_ATTR_TEXT attribute. The possible values for the attribute are defined in the mv_barcode_generate_attr_text_e enumeration. The default value is MV_BARCODE_GENERATE_ATTR_TEXT_INVISIBLE.
-
-
For barcode detection:
-
To handle camera preview images, include the <camera.h> header file:
#include <camera.h>
-
Create a structure for storing the data required for barcode detection engine configuration:
typedef struct _bardetdata_s { // Camera display variables Evas_Object *win; Evas_Object *rect; Evas *evas; int preview_width; int preview_height; // Media source handle mv_source_h g_source; // Barcode detection engine handle mv_engine_config_h g_engine_cfg; // Camera handle camera_h g_camera; } bargendata_s; static bardetdata_s bardetdata;
-
Create a source handle using the mv_create_source() function with the mv_source_h member of the detection data structure as the out parameter:
int error_code = 0; error_code = mv_create_source(&bardetdata.g_source); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
The source stores the barcode to be detected and all related data. You manage the source through the source handle.
-
Configure the barcode detection engine using the mv_create_engine_config() function. The function configures the engine with default attribute values.
int error_code = 0; error_code = mv_create_engine_config(&bardetdata.g_engine_cfg); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
For example, to define the detection target, use the mv_engine_config_set_int_attribute() function with the MV_BARCODE_DETECT_ATTR_TARGET attribute. The possible values are defined in the mv_barcode_detect_attr_target_e enumeration. The default value is MV_BARCODE_DETECT_ATTR_TARGET_ALL.
-
To provide camera preview images, create the camera handle, set the camera display and the camera preview callback, and start the camera preview:
// Create the camera handle error_code = camera_create(CAMERA_DEVICE_CAMERA0, &bardetdata.g_camera); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } // Set the camera display error_code = camera_set_display(bardetdata.g_camera, CAMERA_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(bardetdata.win)); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } // Get the camera preview resolution error_code = camera_get_preview_resolution(bardetdata.g_camera, &bardetdata.width, &bardetdata.height); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code %d", error_code); } // Set the camera preview callback error_code = camera_set_media_packet_preview_cb(bardetdata.g_camera, _camera_media_packet_preview_cb, NULL); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } // Start the camera preview error_code = camera_start_preview(barcodeAppData.g_camera); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
For more information about the camera_set_display() function, see Initializing the Camera in the Camera tutorial.
-
Generating Barcodes
To generate a barcode:
-
Set the barcode type. In case of the QR type, also set the error correction level, encoding mode, and version.
bargendata.type = MV_BARCODE_QR; bargendata.ecc = MV_BARCODE_QR_ECC_LOW; bargendata.mode = MV_BARCODE_QR_MODE_BYTE; bargendata.version = 20;
-
To generate the barcode into memory:
-
Create a source handle using the mv_create_source() function with the mv_source_h member of the generation data structure as the out parameter:
int error_code = 0; error_code = mv_create_source(&bargendata.g_source); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code= %d", error_code); }
The source handle is used to save the generated barcode and related data into the source, and to access the barcode and related data from the source.
-
Generate the barcode using the mv_barcode_generate_source() function:
error_code = mv_barcode_generate_source(bargendata.g_engine_cfg, "MediaVision-Tutorial-QRcode", bargendata.type, bargendata.mode, bargendata.ecc, bargendata.version, bargendata.g_source); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
-
Retrieve the width, height, color space, and memory address of the barcode using the mv_source_get_width(), mv_source_get_height(), mv_source_get_colorspace(), and mv_source_get_buffer() functions:
mv_colorspace_e image_colorspace = MEDIA_VISION_COLORSPACE_INVALID; unsigned int image_width = 0; unsigned int height_height = 0; unsigned char *image_buffer_ptr = NULL; unsigned int image_buffer_size = 0; error_code = mv_source_get_width(bargendata.g_source, &image_width); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } error_code = mv_source_get_height(bargendata.g_source, &image_height); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } error_code = mv_source_get_colorspace(bargendata.g_source, &image_colorspace); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } error_code = mv_source_get_buffer(bargendata.g_source, &image_buffer_ptr, &image_buffer_size); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
-
After the barcode generation is complete, destroy the source handle using the mv_destroy_source() function:
error_code = mv_destroy_source(bargendata.g_source); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
-
-
To generate the barcode into a file:
-
Define the file format and image resolution:
bargendata.width = 800; bargendata.height = 800; bargendata.image_format = MV_BARCODE_IMAGE_FORMAT_PNG;
-
Generate the barcode using the mv_barcode_generate_image() function.
The following example code saves the generated file in the /opt/usr/media directory with the file name mv_barcode_qrcode.png:
error_code = mv_barcode_generate_image(bargendata.g_engine_cfg, "MediaVision-Tutorial-QRcode", bargendata.width, bargendata.height, bargendata.type, bargendata.mode, bargendata.ecc, bargendata.version, "/opt/usr/media/mv_barcode_qrcode.png", bargendata.image_format); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
-
-
Destroy the barcode generation engine handle using the mv_destroy_engine_config() function:
error_code = mv_destroy_engine_config(bargendata.g_engine_cfg); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
Detecting Barcodes
To detect barcodes:
-
To access the camera preview images in which to detect barcodes:
-
Implement the _camera_media_packet_preview_cb() callback. This callback is invoked by the camera_start_preview() function after each captured preview image and returns a handle for the media packet containing the image.
-
In the callback, fill the source with the media packet using the mv_source_fill_by_media_packet() function. This function takes as parameters the source handle and the media packet handle.
The image is now stored in the source, and you can access the image through the source handle.
static void _camera_media_packet_preview_cb(media_packet_h pkt, void *user_data) { mv_rectangle_s mv_roi = {{0,0}, bardetdata.width, bardetdata.height}; if (pkt == NULL) { return; } error_code = mv_source_fill_by_media_packet(bardetdata.g_source, pkt); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error code); } if (pkt) { error_code = media_packet_destroy(pkt); pkt = NULL; }
-
-
In the _camera_media_packet_preview_cb() callback, detect barcodes in the image using the mv_barcode_detect() function:
error_code = mv_barcode_detect(bardetdata.g_source, bardetdata.g_engine_cfg, mv_roi, _barcode_detected_cb, NULL); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } }
The ROI (region of interest) feature allows you to define a rectangular region of the image in which to detect barcodes. In the above example code, the whole image is set as the ROI.
-
Implement a callback that is invoked by the mv_barcode_detect() function after it has finished processing the image for barcodes.
Use the callback to handle the detection results, and to clear the source for the next image. To clear the source, use the mv_source_clear() function.
The following example code implements a callback that prints the number of detected barcodes and their messages, if the number is greater than zero. The code also clears the source of the image data.
static void _barcode_detected_cb(mv_source_h source, mv_engine_config_h engine_cfg, const mv_quadrangle_s *barcode_locations, const char *message[], const mv_barcode_type_e *types, int number_of_barcodes, void *user_data) { int i = 0; char type[50] = {‘\0}; // Clear the source for the next preview image mv_source_clear(mv_source); if (number_of_barcode > 0) { dlog_print(DLOG_INFO, LOG_TAG, "the number of barcodes: %d", number_of barcode); for (i = 0; i < number_of_barcodes; i++) { dlog_print(DLOG_INFO, LOG_TAG, "%d >> message: %s\n", I, messages[i]); } } }
-
After the barcode detection is complete, stop the camera preview, unset the camera preview callback function, and destroy the camera handle:
error_code = camera_unset_media_packet_preview_cb(bardetdata.g_camera); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } error_code = camera_stop_preview(bardetdata.g_camera); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } error_code = camera_destroy(bardetdata.g_camera); if (error_code != CAMERA_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }
For more information, see Releasing Resources in the Camera tutorial.
-
Destroy the source and barcode detection engine handles using the mv_destroy_source() and mv_destroy_engine_config() functions:
error_code = mv_destroy_engine_config(bardetdata.g_engine_cfg); if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); } error_code = mv_destroy_source(bardetdata.g_source) if (error_code != MEDIA_VISION_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "error code = %d", error_code); }