Getting Started with C++¶
The Spinnaker C++ API provides full-featured native access to USB3 Vision and GigE Vision cameras with GenICam integration and a QuickSpin convenience layer.
Prerequisites¶
- Spinnaker SDK installed (download)
- C++ compiler (Visual Studio 2015+ on Windows, GCC on Linux, Clang on macOS)
- A supported Teledyne camera connected via USB3 or GigE
Basic Acquisition Example¶
The canonical example is located at src/Acquisition/Acquisition.cpp in the SDK.
Below is the essential workflow:
#include "Spinnaker.h"
using namespace Spinnaker;
int main()
{
// Get the system singleton
SystemPtr system = System::GetInstance();
// Retrieve camera list
CameraList camList = system->GetCameras();
// Get the first camera
CameraPtr pCam = camList.GetByIndex(0);
// Initialize (populates GenICam nodemap)
pCam->Init();
// Configure acquisition mode to continuous
pCam->AcquisitionMode.SetValue(AcquisitionMode_Continuous);
// Begin acquiring images
pCam->BeginAcquisition();
// Retrieve and process images
for (int i = 0; i < 10; i++)
{
ImagePtr pImage = pCam->GetNextImage(1000);
if (!pImage->IsIncomplete())
{
// Process image...
cout << "Image " << i << ": " << pImage->GetWidth()
<< " x " << pImage->GetHeight() << endl;
}
// Release image back to the buffer pool
pImage->Release();
}
// Clean up
pCam->EndAcquisition();
pCam->DeInit();
pCam = nullptr;
camList.Clear();
system->ReleaseInstance();
return 0;
}
Key Concepts¶
GenICam Nodemap¶
After calling Init(), access the camera's GenICam nodemap to configure features:
INodeMap& nodeMap = pCam->GetNodeMap();
CEnumerationPtr ptrAcquisitionMode = nodeMap.GetNode("AcquisitionMode");
Always check node availability before access:
QuickSpin¶
QuickSpin provides direct property access for common parameters:
Transport Layer Device Nodemap¶
Device information is available before Init():
INodeMap& tlNodeMap = pCam->GetTLDeviceNodeMap();
CStringPtr ptrSerial = tlNodeMap.GetNode("DeviceSerialNumber");
Feature Snippets¶
Hardware Triggering¶
Enable trigger mode with GPIO Line 0 as the rising-edge source:
CEnumerationPtr triggerMode = nodeMap.GetNode("TriggerMode");
triggerMode->SetIntValue(triggerMode->GetEntryByName("On")->GetValue());
CEnumerationPtr triggerSource = nodeMap.GetNode("TriggerSource");
triggerSource->SetIntValue(triggerSource->GetEntryByName("Line0")->GetValue());
CEnumerationPtr triggerSelector = nodeMap.GetNode("TriggerSelector");
triggerSelector->SetIntValue(triggerSelector->GetEntryByName("FrameStart")->GetValue());
CEnumerationPtr triggerActivation = nodeMap.GetNode("TriggerActivation");
triggerActivation->SetIntValue(triggerActivation->GetEntryByName("RisingEdge")->GetValue());
See also: src/Trigger/Trigger.cpp
Setting Exposure Time¶
ExposureTime is the duration the electronic shutter stays open. Disable auto-exposure first:
// QuickSpin
cam->ExposureAuto.SetValue(ExposureAutoEnums::ExposureAuto_Off);
cam->ExposureTime.SetValue(20000.0f); // microseconds (20 ms)
See also: src/Exposure/Exposure.cpp
Setting Black Level¶
BlackLevel is the GenICam feature that represents the DC offset applied to the video
signal (known as Brightness in FlyCapture2):
// QuickSpin
cam->BlackLevelSelector.SetValue(BlackLevelSelectorEnums::BlackLevelSelector_All);
cam->BlackLevel.SetValue(1.5f); // 1.5%
// GenICam
CEnumerationPtr ptrBlackLevelSelector = nodeMap.GetNode("BlackLevelSelector");
ptrBlackLevelSelector->SetIntValue(
ptrBlackLevelSelector->GetEntryByName("All")->GetValue());
CFloatPtr ptrBlackLevel = nodeMap.GetNode("BlackLevel");
ptrBlackLevel->SetValue(1.5);
Setting Gain¶
Setting Gamma¶
Setting White Balance¶
// QuickSpin
cam->BalanceWhiteAuto.SetValue(BalanceWhiteAutoEnums::BalanceWhiteAuto_Off);
cam->BalanceRatioSelector.SetValue(BalanceRatioSelectorEnums::BalanceRatioSelector_Red);
cam->BalanceRatio.SetValue(1.5f);
Software Buffers¶
Control the number of image buffers allocated for acquisition:
// GenICam — TL Stream nodemap
INodeMap& sNodeMap = cam->GetTLStreamNodeMap();
CIntegerPtr ptrBufferCount = sNodeMap.GetNode("StreamDefaultBufferCount");
ptrBufferCount->SetValue(10);
Accessing Raw Bayer Data¶
Raw pixel data is accessible via GetData(). In 8-bit Bayer modes (e.g., BayerRG8)
each byte represents one pixel. The top-left corner is row 0, column 0:
// Assuming 640x480 BayerRG8 — pixel layout is RGGB
ImagePtr pResultImage = cam->GetNextImage();
char* data = (char*)pResultImage->GetData();
// data[0] = Row 0, Column 0 → red (R)
// data[1] = Row 0, Column 1 → green (G)
// data[640] = Row 1, Column 0 → green (G)
// data[641] = Row 1, Column 1 → blue (B)
The current pixel format (PixelFormat) and PixelColorFilter indicate the Bayer tile
mapping for the connected camera.
Grabbing Images¶
cam->BeginAcquisition();
ImagePtr pResultImage = cam->GetNextImage(1000); // 1 s timeout
// Check for incomplete frames
ImageStatus imageStatus = pResultImage->GetImageStatus();
if (pResultImage->IsIncomplete())
{
// imageStatus gives the specific reason
}
pResultImage->Release(); // always release back to the buffer pool
cam->EndAcquisition();
ImageStatus values: IMAGE_NO_ERROR, IMAGE_CRC_CHECK_FAILED, IMAGE_MISSING_PACKETS, IMAGE_DATA_INCOMPLETE, and others.
Loading and Saving Images¶
// Save acquired image
pResultImage->Save("image.jpg");
// Load a raw image from disk
int width = 1280, height = 1024;
unsigned char* data = (unsigned char*)malloc(width * height);
FILE* f = fopen("image.raw", "rb");
fread(data, 1, width * height, f);
ImagePtr loadImage = Image::Create(width, height, 0, 0,
PixelFormatEnums::PixelFormat_BayerRG8, data);
loadImage->Convert(PixelFormat_Mono8);
loadImage->Save("image_converted.jpg");
Chunk Data¶
Chunk data attaches metadata (frame counter, exposure time, etc.) to each image:
// Enable chunk data (QuickSpin)
cam->ChunkSelector.SetValue(ChunkSelectorEnums::ChunkSelector_ExposureTime);
cam->ChunkEnable.SetValue(true);
cam->ChunkModeActive.SetValue(true);
// Retrieve after acquisition
const ChunkData& chunkData = rawImage->GetChunkData();
float64_t exposureTime = chunkData.GetExposureTime();
See also: src/ChunkData/ChunkData.cpp
Event Handling¶
Spinnaker provides interface events (device arrival/removal) and device events (e.g., exposure end):
// Interface event — camera arrival and removal
class InterfaceEventsHandler : public InterfaceEvent
{
public:
void OnDeviceArrival()
{
std::cout << "A camera arrived" << std::endl;
}
void OnDeviceRemoval(uint64_t deviceSerialNumber)
{
std::cout << "Camera removed: " << deviceSerialNumber << std::endl;
}
};
InterfaceEventsHandler handler;
cam->RegisterEvent(handler);
// Device event — exposure end
CEnumerationPtr pEnum = nodeMap.GetNode("EventSelector");
pEnum->SetIntValue(pEnum->GetEntryByName("EventExposureEnd")->GetValue());
CEnumerationPtr pBool = nodeMap.GetNode("EventNotification");
pBool->SetIntValue(1);
class DeviceEventHandler : public DeviceEvent
{
public:
void OnDeviceEvent(GenICam::gcstring eventName)
{
std::cout << "Device event: " << eventName
<< " ID=" << GetDeviceEventId() << std::endl;
}
};
DeviceEventHandler devHandler;
cam->RegisterEvent(devHandler);
See also: src/NodeMapCallback/NodeMapCallback.cpp, src/DeviceEvents/DeviceEvents.cpp
Error Handling¶
try
{
cam.Init();
}
catch (Spinnaker::Exception& e)
{
std::cout << "Error: " << e.what() << std::endl;
}
Logging¶
Spinnaker supports five log levels: Error, Warn, Notice, Info, Debug. Register a logging callback on the system object:
class LogCallback : Spinnaker::LoggingEvent
{
void OnLogEvent(LoggingEventDataPtr loggingEventDataPtr)
{
// handle log event
}
};
SystemPtr system = System::GetInstance();
LogCallback callBackClass;
system->RegisterLoggingEvent((Spinnaker::LoggingEvent&)callBackClass);
system->SetLoggingEventPriorityLevel(LOG_LEVEL_DEBUG);
Logs are saved to C:\ProgramData\Spinnaker\Logs. See also: src/Logging/Logging.cpp
Design Conventions¶
Resource Management¶
The C++ API uses reference-counted smart pointers (SystemPtr, CameraPtr,
ImagePtr). Resources are released automatically when the last pointer goes
out of scope — no explicit delete is required:
SystemPtr system = System::GetInstance();
CameraList camList = system->GetCameras();
CameraPtr pCam = camList.GetByIndex(0);
pCam->Init();
// ... configure and acquire ...
pCam->DeInit();
camList.Clear();
// system released when 'system' goes out of scope
Acquire → DeInit → Clear order
Always call DeInit() on each camera and Clear() on the camera list
before the SystemPtr goes out of scope. Releasing the system while
cameras are still initialized results in exception thrown.
QuickSpin¶
QuickSpin provides direct typed property access on the camera object, avoiding verbose node map lookups. It wraps the same underlying GenICam nodes:
// GenICam node map access (verbose)
INodeMap& nodeMap = pCam->GetNodeMap();
CEnumerationPtr pExposureAuto = nodeMap.GetNode("ExposureAuto");
pExposureAuto->SetIntValue(pExposureAuto->GetEntryByName("Off")->GetValue());
// QuickSpin equivalent (preferred for standard parameters)
pCam->ExposureAuto.SetValue(ExposureAuto_Off);
pCam->ExposureTime.SetValue(5000.0f); // microseconds
Error Handling¶
The C++ API throws Spinnaker::Exception on failure. Wrap acquisition and
configuration code in try/catch blocks:
try
{
pCam->BeginAcquisition();
}
catch (Spinnaker::Exception& e)
{
std::cout << "Error: " << e.what() << std::endl;
}
Quick Reference¶
System & Discovery¶
| Class / Method | Description |
|---|---|
System::GetInstance() |
Obtain the system singleton |
System::ReleaseInstance() |
Release the system singleton |
System::GetCameras() |
Enumerate connected cameras |
System::GetLibraryVersion() |
Query SDK version at runtime |
Camera Lifecycle¶
| Class / Method | Description |
|---|---|
CameraList |
List of detected cameras |
CameraPtr |
Camera object for configuration and acquisition |
Camera::Init() |
Initialize the camera and populate node map |
Camera::DeInit() |
De-initialize the camera |
Camera::BeginAcquisition() |
Start image acquisition |
Camera::EndAcquisition() |
Stop image acquisition |
Image Handling¶
| Class / Method | Description |
|---|---|
ImagePtr |
Captured image with pixel data access |
Image::IsIncomplete() |
Check for dropped or incomplete frame |
Image::GetData() |
Access raw pixel buffer |
Image::GetWidth() / GetHeight() |
Image dimensions in pixels |
Image::GetPixelFormat() |
Current pixel format |
Image::Release() |
Return image to acquisition buffer pool |
ImageProcessor |
Image format conversion utility |
ImageProcessor::Convert() |
Convert to a different pixel format |
Node Map & Configuration¶
| Class / Method | Description |
|---|---|
Camera::GetNodeMap() |
Access GenICam node map (requires Init()) |
Camera::GetTLDeviceNodeMap() |
Transport layer device node map (pre-Init()) |
Camera::GetTLStreamNodeMap() |
Transport layer stream node map |
INodeMap::GetNode(name) |
Retrieve a node by name |
CIntegerPtr |
Integer node accessor |
CFloatPtr |
Float node accessor |
CEnumerationPtr |
Enumeration node accessor |
CBooleanPtr |
Boolean node accessor |
Events & Callbacks¶
| Class | Description |
|---|---|
ImageEventHandler |
Base class for image arrival callbacks |
DeviceEventHandler |
Base class for device-level events |
LoggingEventHandler |
Base class for SDK log message callbacks |
Camera::RegisterEventHandler() |
Attach an event handler to a camera |
Camera::UnregisterEventHandler() |
Detach an event handler |
Exception Reference¶
The C++ API signals all errors by throwing Spinnaker::Exception. The
exception carries the original error code, a human-readable message, and
the source location:
| Member | Description |
|---|---|
what() |
Human-readable error description |
GetError() |
Numeric error code (spinError) |
GetFileName() |
Source file where the error originated |
GetFunctionName() |
Function name where the error originated |
GetLineNumber() |
Line number where the error originated |
GetFullErrorMessage() |
Concatenated full error details |
Common error codes are listed in the C API Error Code Reference.
Known Issues & Limitations¶
Windows-specific
ImageProcessor GPU acceleration requires DirectX 11.
Falls back to CPU silently if unavailable.
Further Reading¶
- C++ API Reference — Full class and function documentation
- Programmer's Guide — Architecture, nodes, image pointer, sequencer, and more
- Streaming Drivers — GigE driver configuration
- SDK Example: Acquisition — Full acquisition example
- SDK Example: Trigger — Hardware and software triggering
- SDK Example: Exposure — Exposure control