Grabbing an Image

This article shows in detail how to set up a data stream from a video capture device and grab a single image.

Opening and Configuring the Video Capture Device

First, the library is initialized, and the first available video capture device is opened:

ic4_init_library(NULL);
 
// Create a grabber object
struct IC4_GRABBER* grabber = NULL;
ic4_grabber_create(&grabber);
 
// Find the first available video capture device
struct IC4_DEVICE_ENUM* enumerator = NULL;
ic4_devenum_create(&enumerator);
ic4_devenum_update_device_list(enumerator);
struct IC4_DEVICE_INFO* info = NULL;
ic4_devenum_get_devinfo(enumerator, 0, &info);
ic4_devenum_unref(enumerator);
 
// Open it
if( !ic4_grabber_device_open(grabber, info) )
{
    print_last_error();
    ic4_devinfo_unref(info);
    goto cleanup_grabber;
}
ic4_devinfo_unref(info);
void ic4_devenum_unref(struct IC4_DEVICE_ENUM *pEnumerator)
Decreases the device enumerator's internal reference count by one.
bool ic4_devenum_update_device_list(struct IC4_DEVICE_ENUM *pEnumerator)
Searches for video capture devices and populates the enumerator's internal device list.
bool ic4_devenum_get_devinfo(const struct IC4_DEVICE_ENUM *pEnumerator, int index, struct IC4_DEVICE_INFO **ppInfo)
Returns a IC4_DEVICE_INFO object describing one of the discovered video capture devices.
bool ic4_devenum_create(struct IC4_DEVICE_ENUM **ppEnumerator)
Creates a new device enumerator.
void ic4_devinfo_unref(struct IC4_DEVICE_INFO *pInfo)
Decreases the device information's internal reference count by one.
bool ic4_grabber_create(struct IC4_GRABBER **ppGrabber)
Creates a new grabber.
bool ic4_grabber_device_open(struct IC4_GRABBER *pGrabber, struct IC4_DEVICE_INFO *dev)
Opens the video capture device specified by the passed IC4_DEVICE_INFO.
bool ic4_init_library(const struct IC4_INIT_CONFIG *init_config)
Initializes the IC Imaging Control 4 C Library.
Device enumerator type.
Device information type.
Represents an opened video capture device, allowing device configuration and stream setup.

Opening the device can fail, so we check for the return value of the function. In case of an error the last error is printed. For details on error handling, see Error Handling.

Then, the device has to be configured. This step is important because in most situations, programs want the camera to be in a defined state before starting operation. In this example, the resolution is configured using the device's IC4_PROPID_WIDTH and IC4_PROPID_HEIGHT properties:

IC4_PROPERTY_MAP* map = NULL;
ic4_grabber_device_get_property_map(grabber, &map);
 
// Set the resolution to 640x480
ic4_propmap_set_value_int64(map, IC4_PROPID_WIDTH, 640);
ic4_propmap_set_value_int64(map, IC4_PROPID_HEIGHT, 480);
 
ic4_propmap_unref(map);
bool ic4_grabber_device_get_property_map(struct IC4_GRABBER *pGrabber, struct IC4_PROPERTY_MAP **ppPropertyMap)
Returns the property map for the currently opened video capture device.
#define IC4_PROPID_HEIGHT
Height of the image provided by the device (in pixels).
Definition C_PropertyConstants.h:699
#define IC4_PROPID_WIDTH
Width of the image provided by the device (in pixels).
Definition C_PropertyConstants.h:1099
void ic4_propmap_unref(struct IC4_PROPERTY_MAP *map)
Decreases the property map's internal reference count by one.
bool ic4_propmap_set_value_int64(struct IC4_PROPERTY_MAP *map, const char *prop_name, int64_t value)
Set the value of a property with a known name to the passed integer value.
Represents the property interface of a component, usually a video capture device.

At this point, an application could also load a prepared device configuration file (using ic4_grabber_device_open_from_state_file or apply a serialized property configuration using ic4_propmap_deserialize).

Setting up the Sink and Data Stream

After the device has been configured, it is time to setup a data stream. To receive image data from the video capture device, a Sink object has to be created. The Snap Sink is the sink most suitable to grab images on demand.

struct IC4_SINK* sink = NULL;
ic4_snapsink_create(&sink);
 
if( !ic4_grabber_stream_setup(grabber, sink, NULL, true) )
{
    print_last_error();
    goto cleanup_sink;
}
bool ic4_grabber_stream_setup(struct IC4_GRABBER *pGrabber, struct IC4_SINK *sink, struct IC4_DISPLAY *display, bool start_acquisition)
Establishes the data stream from the device.
bool ic4_snapsink_create(struct IC4_SINK **ppSink, const struct IC4_SNAPSINK_CONFIG *config)
Creates a new Snap Sink.
Represents a sink, allowing programmatic access to image data.

The data stream is established by calling ic4_grabber_stream_setup, passing the sink as a parameter. We also set the start_acquisition parameter to true, so that the device is instructed to start image acquisition immediately after the data stream was created.

After the streamSetup call returned successfully, the device is continuously sending images to the host computer.

Grabbing an Image

By calling ic4_snapsink_snap_single, the sink is instructed to wait for the next image to arrive at the sink and, if an image is received during the specified timeout period, return it:

struct IC4_IMAGE_BUFFER* buffer = NULL;
if( !ic4_snapsink_snap_single(sink, &buffer, 1000) )
{
    printf("Failed to snap image\n");
    print_last_error();
    goto cleanup_sink;
}
 
if( !ic4_imagebuffer_save_as_bmp(buffer, "test.bmp") )
{
    printf("Failed to save image buffer\n");
    print_last_error();
    goto cleanup_sink;
}
bool ic4_imagebuffer_save_as_bmp(struct IC4_IMAGE_BUFFER *pImageBuffer, const char *file_path, const struct IC4_IMAGEBUFFER_SAVE_OPTIONS_BMP *options)
Saves an image buffer as a Bitmap file.
bool ic4_snapsink_snap_single(const struct IC4_SINK *pSink, struct IC4_IMAGE_BUFFER **ppImageBuffer, int64_t timeout_ms)
Grabs a single image out of the video stream received from the video capture device.
Represents an image buffer.

In this example, we print information about the received image and save it in a bitmap file.

Stopping the Data Stream

A call to ic4_grabber_stream_stop stops the data stream:

    // Stop the data stream.
    ic4_grabber_stream_stop(grabber);
 
    // Clean up grabber and sink
cleanup_sink:
    ic4_sink_unref(sink);
cleanup_grabber:
    ic4_grabber_unref(grabber);
bool ic4_grabber_stream_stop(struct IC4_GRABBER *pGrabber)
Stops a data stream that was previously set up by a call to ic4_grabber_stream_setup().
void ic4_grabber_unref(struct IC4_GRABBER *pGrabber)
Decreases the grabber's internal reference count by one.
void ic4_sink_unref(struct IC4_SINK *pSink)
Decreases the sink's internal reference count by one.

Stopping acquisition and data stream is important, because keeping the acquisition active would waste CPU and memory resources as well as bandwidth on the transmission medium.