Spinnaker C
4.3.0.189
 
Programmer's Guide
C Programmer's Guide

C Programmer's Guide Contents

Fundamentals of Spinnaker

Architecture of Spinnaker

Examples

Nodes

Accessing Camera Parameters

C# Graphical User Interface API

Camera XML

Recommended Development Environment

Instantiate a Single Camera and Multiple Cameras

Popular Features in Spinnaker

Enumeration

Asynchronous Hardware Triggering

Setting Black Level

Setting Exposure Time

Setting Gain

Setting Gamma

Setting White Balance

Accessing Raw Bayer Data

Setting Number of Software Buffers

Basic Features

Event Handling

Grabbing Images

Error Handling

Advanced Features

Sequencer

Logic Block

Logging

User Set

Architecture of Spinnaker API

Spinnaker API is built around the GenICam standard, which offers a generic programming interface for various cameras and interfaces. Spinnaker is an extension of GenAPI. Spinnaker provides quick and easy access to your camera.

Spinnaker API includes two major components:

Image Acquisition

This is the acquisition engine that is responsible for setting up image buffers and image grabbing.

Camera Configuration

This is the configuration engine that is responsible for controlling your camera. This component consists of QuickSpin API, which is a wrapper that makes GenAPI easy to use.

Examples

Included with the Spinnaker SDK are a number of source code examples to help you get started. These examples are provided for C, C++, C#, and VB.NET languages and are precompiled for your convenience.

The table below describes the available Spinnaker SDK examples.

Spinnaker Example Description
Acquisition Enumerate, start acquisition, and grab images
AcquisitionMultipleCamera How to capture images from multiple cameras simultaneously
ChunkData How to get chunk data on an image, either from the nodemap or from the image itself
DeviceEvents Create a handler to access device events
Enumeration Enumerate interfaces and cameras
EnumerationEvents Explore arrival and removal events on interfaces and the system
ImageEvents Image events shows how to acquire images using the image event handler.
ImageFormatControl Configure a custom image size and format
Logging Create a logging event handler
LookupTable Configure lookup tables for the customization and control of individual pixels
NodeMapCallback Create, register, use, and unregister callbacks
NodeMapInfo How to retrieve node map information
SaveToVideo Save images in various video formats
Sequencer
(Blackfly S and Oryx only)
Capture multiple images with different parameters in a sequence
SpinSimpleGUI_MFC Graphical User Interface for evaluating and setting camera parameters
Trigger Trigger shows how to trigger the camera.

Nodes

Every GenICam compliant camera has an XML description file. The XML describes camera features, their interdependencies, and all other information like availability, access control, and minimum and maximum values. These features include Gain, Exposure Time, Image Format, and others. The elements of a camera description file are represented as software objects called Nodes. A Node map is a list of nodes created dynamically at run time.

Node Map

To access camera properties such as setting image width:

C API

spinCameraGetNodeMap(hCam,&hNodeMap); //spinCamera hCam

spinNodeHandle hNode;
int64_t value = 0;
error = spinNodeMapGetNode(hNodeMap,"Width",&hNode);
error = spinIntegerSetValue(hNode, 320);

Accessing Camera Parameters

You can access parameters via the Spinnaker C API. Spinnaker C API closely resembles GenAPI. GenAPI is an open source API for configuring GenICam cameras maintained by the European Machine Vision Association (EMVA).

Below is an example Spinnaker C API to turn off auto exposure.

Spinnaker C API to turn off auto exposure

// Turn off auto exposure
spinNodeHandle hExposureAutoSelector = NULL;
spinNodeHandle hExposureAutoSelectorChoice = NULL;
int64_t exposureAutoSelectorChoice = 0;

spinNodeMapGetNode(hNodeMap, "ExposureAuto", &hExposureAutoSelector);
spinEnumerationGetEntryByName(hExposureAutoSelector, "Off", &hExposureAutoSelectorChoice);
spinEnumerationEntryGetValue(hExposureAutoSelectorChoice, &exposureAutoSelectorChoice);
spinEnumerationSetIntValue(hExposureAutoSelectorChoice, exposureAutoSelectorChoice);

C# Graphical User Interface API

For applications that want to take advantage of Spinnaker's graphical user elements, graphical user interface (GUI) controls are available. GUI controls are divided into static and dynamic categories. Static GUI controls include the CameraSelectionDialog, display window, and property grid window. The GUI dynamically loads the camera's features from the firmware. Therefore, new firmware has the ability to add GUI controls to the same application, without recompiling.

Static GUI Dialogs

//To show image drawing window

GUIFactory AcquisitionGUI = new GUIFactory ();

AcquisitionGUI.ConnectGUILibrary(cam);

ImageDrawingWindow AcquisitionDrawing = AcquisitionGUI.GetImageDrawingWindow();

AcquisitionDrawing.Connect(cam);

AcquisitionDrawing.Start();

AcquisitionDrawing.ShowModal();

//To show camera selection window

GUIFactory AcquisitionGUI = newGUIFactory ();

AcquisitionGUI.ConnectGUILibrary(cam);

CameraSelectionWindow camSelection = AcquisitionGUI.GetCameraSelectionWindow();

camSelection.ShowModal(true);

//To show property grid window

GUIFactory AcquisitionGUI = new GUIFactory ();

AcquisitionGUI.ConnectGUILibrary(cam);

PropertyGridWindow propWindow = AcquisitionGUI.GetPropertyGridWindow();

propWindow.Connect(cam);

propWindow.ShowModal();

Dynamic GUI Control

GUIFactory dynamicGUI = new GUIFactory ();

dynamicGUI.ConnectGUILibrary(cam);

// Get dialog name via dynamicGUI.GetDialogNameList()

Window dlg = dynamicGUI.GetDialogByName(dialogName);

dlg.Owner = Window .GetWindow(this );

dlg.Show();

Camera XML

The camera's XML file contains information such as feature naming, register mapping, and dependencies between features. It is typical for GenICam-compliant software to cache the XML file for quicker access to the camera's definition. Spinnaker caches the XML file in a binary format to achieve better performance.

Camera XML files are located in:

C:\ProgramData\Spinnaker\XML

Recommended Environment

Spinnaker supports the following list of operating systems and development environments.

OS Compatibility
(32- and 64-bit)

Windows XP
Windows 7
Windows 8.1
Windows 10

Language Support

C
C++
C#
VB.NET

Compiler Support

Visual Studio 2010
Visual Studio 2013
Visual Studio 2015

Interface Support

USB3 Vision 1.0

Instantiate Cameras

Before you can instantiate a camera, you must create and initialize a system object. The System Singleton object is used to retrieve the list of interfaces (USB 3.1 or GigE) and cameras available. You must call ReleaseInstance() at the end of your program to free up the system object.

Multiple cameras can only be instantiated one at a time.

Instantiate multiple cameras
(C)

spinSystem hSystem = NULL;

spinCameraList hCameraList = NULL;

spinSystemGetInstance(&hSystem);

spinSystemGetCameras(hSystem, &hCameraList);

size_t numCameras = 0;

err = spinCameraListGetSize(hCameraList, &numCameras);

>unsigned int i = 0;

for (i = 0; i < numCameras; i++)

{

   spinCamera hCamera = NULL;

   err = spinCameraListGet(hCameraList, i, &hCamera);

   err = spinCameraInit(hCamera);

}

spinSystemReleaseInstance(hSystem);

Enumeration

The snippet below detects the number of cameras connected and enumerates them from an index.

Spinnaker C API

spinCamera hCamera = NULL;
spinCameraListGetSize(hCameraList, &numCameras);
for (i = 0; i < numCameras; i++)
{
    spinCameraListGet(hCameraList, i, &hCamera);
    spinCameraInit(hCam);
}

Asynchronous Hardware Triggering

The snippet below does the following:

  • Enables Trigger Mode
  • Configures GPIO0/Line0 as the trigger input source
  • Specifies the trigger signal polarity as an active high (rising edge) signal
Spinnaker C API

spinNodeHandle hTriggerMode = NULL;
spinNodeHandle hTriggerModeOn = NULL;
int64_t triggerModeOn = 0;

err = spinNodeMapGetNode(hNodeMap, "TriggerMode", &hTriggerMode);
err = spinEnumerationGetEntryByName(hTriggerMode, "On", &hTriggerModeOn);
err = spinEnumerationEntryGetValue(hTriggerModeOn, &triggerModeOn);
err = spinEnumerationSetIntValue(hTriggerMode, triggerModeOn);

spinNodeHandle hTriggerSource = NULL;
spinNodeHandle hTriggerSourceChoice = NULL;
int64_t triggerSourceChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "TriggerSource", &hTriggerSource);
err = spinEnumerationGetEntryByName(hTriggerSource, "Line0", &hTriggerSourceChoice);
err = spinEnumerationEntryGetValue(hTriggerSourceChoice, &triggerSourceChoice);
err = spinEnumerationSetIntValue(hTriggerSource, triggerSourceChoice);

spinNodeHandle hTriggerSelector = NULL;
spinNodeHandle hTriggerSelectorChoice = NULL;
int64_t triggerSelectorChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "TriggerSelector", &hTriggerSelector);
err = spinEnumerationGetEntryByName(hTriggerSource, "FrameStart", &hTriggerSelectorChoice);
err = spinEnumerationEntryGetValue(hTriggerSelectorChoice, &triggerSourceChoice);
err = spinEnumerationSetIntValue(hTriggerSelector, triggerSelectorChoice);

spinNodeHandle hTriggerActivation = NULL;
spinNodeHandle hTriggerActivationChoice = NULL;
int64_t triggerActivationChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "TriggerActivation", &hTriggerActivation);
err = spinEnumerationGetEntryByName(hTriggerActivation, "RisingEdge", &hTriggerActivationChoice);
err = spinEnumerationEntryGetValue(hTriggerActivationChoice, &triggerSourceChoice);
err = spinEnumerationSetIntValue(hTriggerActivation, triggerActivationChoice);

Setting Black Level

BlackLevel is the GenICam feature that represents the DC offset that is applied to the video signal. This example compares the mechanism used to set this feature in both environments.

Spinnaker C API

// Black Level is also referred to as brightness
spinNodeHandle hBlackLevelSelector = NULL;
spinNodeHandle hBlackLevelSelectorChoice = NULL;
int64_t blackLevelSelectorChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "BlackLevelSelector", &hBlackLevelSelector);
err = spinEnumerationGetEntryByName(hBlackLevelSelector, "All", &hBlackLevelSelectorChoice);
err = spinEnumerationEntryGetIntValue(hBlackLevelSelectorChoice, &blackLevelSelectorChoice);
err = spinEnumerationSetIntValue(hBlackLevelSelectorChoice, blackLevelSelectorChoice);

//Set the value of black level to 1.5%.
spinNodeHandle hBlackLevel;
err = spinNodeMapGetNode(hNodeMap, "BlackLevel", &hBlackLevel);
err = spinFloatSetValue(hBlackLevel, 1.5);

Setting Exposure Time

ExposureTime refers to the amount of time that the camera's electronic shutter stays open. This example sets your camera's exposure/shutter time to 20 milliseconds.

Spinnaker
C API

// Turn off auto exposure
spinNodeHandle hExposureAutoSelector = NULL;
spinNodeHandle hExposureAutoSelectorChoice = NULL;
int64_t exposureAutoSelectorChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "ExposureAuto", &hExposureAutoSelector);
err = spinEnumerationGetEntryByName(hExposureAutoSelector, "Off", &hExposureAutoSelectorChoice);
err = spinEnumerationEntryGetValue(hExposureAutoSelectorChoice, &exposureAutoSelectorChoice);
err = spinEnumerationSetIntValue(hExposureAutoSelectorChoice, exposureAutoSelectorChoice);

//Set exposure mode to "Timed"
spinNodeHandle hExposureModeSelector = NULL;
spinNodeHandle hExposureModeSelectorChoice = NULL;
int64_t exposureModeSelectorChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "ExposureAuto", &hExposureModeSelector);
err = spinEnumerationGetEntryByName(hExposureModeSelector, "Timed", &hExposureModeSelectorChoice);
err = spinEnumerationEntryGetValue(hExposureModeSelectorChoice, &exposureModeSelectorChoice);
err = spinEnumerationSetIntValue(hExposureModeSelectorChoice, exposureModeSelectorChoice);

//Set value of exposure time to 20000 microseconds
spinNodeHandle hExposureTime;
err = spinNodeMapGetNode(hNodeMap, "ExposureTime", &hExposureTime);
err = spinIntegerSetValue(hExposureTime, 20000);

Setting Gain

The following code snippet adjusts gain to 10.5 dB.

Spinnaker
C API

//Turn auto gain off
spinNodeHandle hGainAutoSelector = NULL;
spinNodeHandle hGainAutoSelectorChoice = NULL;
int64_t gainAutoSelectorChoice = 0;

err = spinNodeMapGetNode(hNodeMap, "GainAuto", &hGainAutoSelector);
err = spinEnumerationGetEntryByName(hGainAutoSelector, "Off", &hGainAutoSelectorChoice);
err = spinEnumerationEntryGetValue(hGainAutoSelectorChoice, &gainAutoSelectorChoice);
err = spinEnumerationSetIntValue(hGainAutoSelectorChoice, gainAutoSelectorChoice);

//Set gain to 10.5 dB
spinNodeHandle hGain;
err = spinNodeMapGetNode(hNodeMap, "Gain", &hGain);
err = spinIntegerSetValue(hGain, 10.5);

Setting Gamma

The following code snippet adjusts gamma to 1.5.

Spinnaker C API

// Enable Gamma
spinNodeHandle hGammaEnable = NULL;

err = spinNodeMapGetNode(hNodeMap, "GammaEnable", &hGammaEnable);
err = spinBooleanSetValue(hGammaEnable, false);

// Set the absolute value of gamma to 1.5
spinNodeHandle hGamma;
err = spinNodeMapGetNode(hNodeMap, "Gamma", &hGamma);
err = spinIntegerSetValue(hGamma, 1.5);

Setting White Balance

The following code snippet adjusts the white balance's red and blue channels.

Spinnaker
C API

//Set auto white balance to off
spinNodeHandle hBalanceWhiteAutoSelector = NULL;
spinNodeHandle hBalanceWhiteAutoSelectorChoice = NULL;
int64_t balanceWhiteAutoSelector = 0;

err = spinNodeMapGetNode(hNodeMap, "BalanceWhiteAuto", &hBalanceWhiteAutoSelector);
err = spinEnumerationGetEntryByName(hBalanceWhiteAutoSelector, "Off", &hBalanceWhiteAutoSelectorChoice);
err = spinEnumerationEntryGetValue(hBalanceWhiteAutoSelectorChoice, &balanceWhiteAutoSelector);
err = spinEnumerationSetIntValue(hBalanceWhiteAutoSelectorChoice, balanceWhiteAutoSelector);

//Select blue channel balance ratio
spinNodeHandle hBalanceRatioSelector = NULL;
spinNodeHandle hBalanceRatioSelectorChoice = NULL;
int64_t balanceRatioSelector = 0;

err = spinNodeMapGetNode(hNodeMap, "BalanceRatioSelector", &hBalanceRatioSelector);
err = spinEnumerationGetEntryByName(hBalanceRatioSelector, "Blue", &hBalanceRatioSelectorChoice);
err = spinEnumerationEntryGetValue(hBalanceRatioSelectorChoice, &balanceRatioSelector);
err = spinEnumerationSetIntValue(hBalanceRatioSelectorChoice, balanceRatioSelector);

//Set the white balance blue channel to 2
spinNodeHandle hBlueRatio;
err = spinNodeMapGetNode(hNodeMap, "BalanceRatio", &hGain);
err = spinIntegerSetValue(hBlueRatio, 2);

//Set the white balance red channel to 2
err = spinNodeMapGetNode(hNodeMap, "BalanceRatioSelector", &hBalanceRatioSelector);
err = spinEnumerationGetEntryByName(hBalanceRatioSelector, "Red", &hBalanceRatioSelectorChoice);
err = spinEnumerationEntryGetValue(hBalanceRatioSelectorChoice, &balanceRatioSelector);
err = spinEnumerationSetIntValue(hBalanceRatioSelectorChoice, balanceRatioSelector);

spinNodeHandle hRedRatio;
err = spinNodeMapGetNode(hNodeMap, "BalanceRatio", &hRedRatio);
err = spinIntegerSetValue(hRedRatio, 2);

Accessing Raw Bayer Data

Raw image data can be accessed programmatically via the getData method of the Spinnaker Image class. In 8 bits per pixel modes such as BayerRG8, the first byte represents the pixel at [row 0, column 0], the second byte at [row 0, column 1], and so on. The top left corner of the image data represents row 0, column 0.

Spinnaker
C API

// Assuming image is 640 x 480 resolution. The current pixel format as well as PixelColorFilter indicate the Bayer Tile Mapping for the camera. For example, BayerRG8 is RGGB.

err = spinCameraGetNextImage(hCam, &hResultImage);
size_t imageSize;
spinImageGetBufferSize(hResultImage, &imageSize);

void **data;
data = (void**)malloc(imageSize * sizeof(void*));

spinImageGetData(hResultImage, data);

// Assuming image is 640 x 480
data[0] = Row 0, Column 0 = red pixel (R)
data[1] = Row 0, Column 1 = green pixel (G)
data[640] = Row 1, Column 0 = green pixel (G)
data[641] = Row 1, Column 1 = blue pixel (B)

Setting Number of Image Buffers

The following code snippet adjusts the number of image buffers that the driver initializes for buffering images on your PC to 11 (default is 10).

Spinnaker C API

spinNodeHandle hGenTLNode = NULL;
int64_t bufferValue;
err = spinNodeMapGetNode(hNodeMapGenTL, "StreamDefaultBufferCount", &hGenTLNode);
err = spinEnumerationEntryGetValue(hNodeMapGenTL, &bufferValue);
err = spinEnumerationSetIntValue(hNodeMapGenTL, 11);

Event Handling

Spinnaker introduces two event classes: interface events and device events.

Interface Event

The interface event class is a new feature that is responsible for registering and deregistering user defined interface events such as device arrival and removal.

Interface Event C

>Interface event (arrival and removal) handling for C is registered by using the below functions:

spinArrivalEventCreate()

spinRemovalEventCreate()

A detailed example for C interface event is included in Spinnaker source code example: EnumerationEvent_C.cpp

Device Event

The device event class is responsible for registering and deregistering user defined device events such as start or end of exposure.

Device Event C

// Create and register ExposureEvent

spinEvent eventExposureEnd = NULL;

error = spinEventCreate(&eventExposureEnd, onSpecificDeviceEvent, NULL);

error = spinCameraRegisterEvent(hCam, eventExposureEnd, "EventExposureEnd");

// Create a function to occur upon specific event occurrences;
//ensure exact same function signature is used

void onSpecificDeviceEvent(const char* pEventName, void* pUserData)
{
    printf("\t// Specific device event %s...\n", pEventName, (char*)pUserData);
}

Grabbing Images

You can grab images using the GetNextImage() function. This function returns an image pointer for the current image. The image pointer should be released whenever you are done with the image. Image pointer, being a smart pointer, is automatically released when set to null or when out of scope.

Image Acquisition (C)

// Begin capturing images
error = spinCameraBeginAcquisition(hCam);

// Retrieve an image
error = spinCameraGetNextImage(hCam, &hResultImage);

// Release image
err = spinCameraReleaseImage(hCam, hResultImage);

Grab Result

In almost all cases, you should check to see if the grabbed image has any errors. To do so, you need to call getImageStatus().

To check for errors in the image (C)

spinImageStatus imageStatus = IMAGE_NO_ERROR;

error = spinImageGetStatus(hResultImage, &imageStatus);

Available error enums

/** Status of images returned from GetNextImage() call. */

enum ImageStatus
{
     IMAGE_NO_ERROR = 0,
/**< Image is returned from GetNextImage() call without any errors. */
     IMAGE_CRC_CHECK_FAILED,
/**< Image failed CRC check. */
     IMAGE_INSUFFICIENT_SIZE,
/**< Image size is smaller than expected. */
     IMAGE_MISSING_PACKETS,
/**< Image has missing packets */
     IMAGE_LEADER_BUFFER_SIZE_INCONSISTENT,
/**< Image leader is incomplete. */
     IMAGE_TRAILER_BUFFER_SIZE_INCONSISTENT,
/**< Image trailer is incomplete. */
     IMAGE_PACKETID_INCONSISTENT,
/**< Image has an inconsistent packet id. */
     IMAGE_DATA_INCOMPLETE,
/**< Image data is incomplete. */
     IMAGE_UNKNOWN_ERROR
/**< Image has an unknown error. */
};

Error Handling

Spinnaker C uses spinError enum for handling errors.

Spinnaker C API

spinError err = spinCameraInit(hCam);

Sequencer

The purpose of a sequencer is to allow you to programmatically control the acquisition parameters of an image sequence. You can define not only how the images are captured (i.e. the camera feature settings) but also when the camera transitions from one acquisition setting to another. This is akin to a state machine diagram where the states correspond to the sequencer set feature settings, and the transition among states corresponds to a particular event that triggers the state machine to move from one state to another.

To configure sequencer on your camera, you can use SpinView's sequencer tab. Or, to programmatically configure it, you can use the C++ Sequencer source code example that is installed along with Spinnaker SDK.

Logic Block

A Logic Block is a collection of combinatorial logic and latches that allows the user to create new, custom signals inside the camera. Each Logic Block is comprised of 2 lookup tables (LUT) with programmable inputs, truth tables and a flip flop output. There is a LUT for both the D input (Value LUT) and the enable input (Enable LUT) of the flip flop. Both LUTs have 3 inputs and thus have 8 configuration bits for their truth table.

For more information, see Using Logic Blocks.

Logging

Spinnaker supports five levels of logging:

  • Error�failures that are non-recoverable (this is the default level)
  • Warning�failures that are recoverable without user intervention
  • Notice�information about events such as camera arrival or disconnect, camera initialize, camera start/stop, or modification of a feature
  • Info�information about recurring events that are generated with every image
  • Debug�information that can be used to troubleshoot the system

You can define the logging level that you want to monitor. Levels are inclusive, that is, if you monitor debug level error, you also monitor all logging levels above it.

For a complete C++ and C# example of Logging, please see Spinnaker SDK source code examples. By default, Spinnaker SDK's SpinView application saves all logging data to:

C:\ProgramData\Spinnaker\Logs

Register Logging (C)

void onLogEvent(const spinLogEvent self, void* pUserData)
{
        ...
}

// Create log event
spinLogEvent logEvent = NULL;

error = spinLogEventCreate(&logEvent, onLogEvent, NULL);

error = spinSystemRegisterLogEvent(hSystem, logEvent);

User Set

User set is an on camera non-volatile memory space that you can use to store camera properties such as exposure and gain.

To check if user set supports the feature that you want to save, you can either query the User Set Feature Selector programmatically or run SpinView: