Skip to content

Getting Started with C# (.NET)

The Spinnaker .NET (Managed) API provides a managed wrapper for Windows desktop applications, GUI integration, and .NET environments.

Prerequisites

  • Spinnaker SDK installed (download)
  • Visual Studio 2015 or later on Windows
  • .NET Framework
  • A supported Teledyne camera connected via USB3 or GigE

Basic Acquisition Example

The canonical example is located at src/Acquisition_CSharp/Acquisition_CSharp.cs in the SDK. Below is the essential workflow:

using SpinnakerNET;
using SpinnakerNET.GenApi;

class Program
{
    static void Main(string[] args)
    {
        // Get the system singleton
        ManagedSystem system = new ManagedSystem();

        // Retrieve camera list
        IList<IManagedCamera> camList = system.GetCameras();

        // Get the first camera
        IManagedCamera cam = camList[0];

        // Initialize
        cam.Init();

        // Configure acquisition mode
        INodeMap nodeMap = cam.GetNodeMap();
        IEnum acquisitionMode = nodeMap.GetNode<IEnum>("AcquisitionMode");
        acquisitionMode.Value = "Continuous";

        // Begin acquisition
        cam.BeginAcquisition();

        // Retrieve images
        for (int i = 0; i < 10; i++)
        {
            using (IManagedImage rawImage = cam.GetNextImage(1000))
            {
                if (!rawImage.IsIncomplete)
                {
                    Console.WriteLine(
                        "Image {0}: {1} x {2}",
                        i, rawImage.Width, rawImage.Height);
                }
            }
        }

        // Clean up
        cam.EndAcquisition();
        cam.DeInit();
        cam.Dispose();
        camList.Clear();
        system.Dispose();
    }
}

Key Concepts

Managed Image Lifecycle

Use using blocks or explicitly call Dispose() to release images and prevent buffer exhaustion.

Node Access

Access GenICam nodes through the managed wrapper:

INodeMap nodeMap = cam.GetNodeMap();
IFloat exposureTime = nodeMap.GetNode<IFloat>("ExposureTime");
exposureTime.Value = 10000.0;

Feature Snippets

Hardware Triggering

Configure the camera for asynchronous hardware triggering on GPIO Line 0 (rising edge):

cam.TriggerMode.Value = TriggerModeEnums.On.ToString();
cam.TriggerSource.Value = TriggerSourceEnums.Line0.ToString();
cam.TriggerSelector.Value = TriggerSelectorEnums.FrameStart.ToString();
cam.TriggerActivation.Value = TriggerActivationEnums.RisingEdge.ToString();
IEnum triggerMode = nodeMap.GetNode<IEnum>("TriggerMode");
triggerMode.Value = "On";

IEnum triggerSource = nodeMap.GetNode<IEnum>("TriggerSource");
triggerSource.Value = "Line0";

IEnum triggerSelector = nodeMap.GetNode<IEnum>("TriggerSelector");
triggerSelector.Value = "FrameStart";

IEnum triggerActivation = nodeMap.GetNode<IEnum>("TriggerActivation");
triggerActivation.Value = "RisingEdge";

Setting Exposure Time

Set the exposure/shutter time to 20 milliseconds (20000 microseconds):

// Turn off auto exposure
cam.ExposureAuto.Value = ExposureAutoEnums.Off.ToString();

// Set exposure mode to "Timed"
cam.ExposureMode.Value = ExposureModeEnums.Timed.ToString();

// Set exposure to 20000 microseconds
cam.ExposureTime.Value = 20000;
IEnum exposureAuto = nodeMap.GetNode<IEnum>("ExposureAuto");
exposureAuto.Value = "Off";

IEnum exposureMode = nodeMap.GetNode<IEnum>("ExposureMode");
exposureMode.Value = "Timed";

IFloat exposureTime = nodeMap.GetNode<IFloat>("ExposureTime");
exposureTime.Value = 20000;

Setting Gain

Adjust analog gain to 10.5 dB:

// Turn auto gain off
cam.GainAuto.Value = GainAutoEnums.Off.ToString();

// Set gain to 10.5 dB
cam.Gain.Value = 10.5;
IEnum gainAuto = nodeMap.GetNode<IEnum>("GainAuto");
gainAuto.Value = "Off";

IFloat gainValue = nodeMap.GetNode<IFloat>("Gain");
gainValue.Value = 10.5;

Event Handling

Spinnaker provides two event classes: interface events (device arrival/removal) and device events (camera-specific events such as end of exposure).

// Interface event — device arrival and removal
class InterfaceEventListener : ManagedInterfaceEvent
{
    protected override void OnDeviceArrival()
    {
        Console.Out.WriteLine("A new device has arrived!");
    }

    protected override void OnDeviceRemoval(UInt64 serialNumber)
    {
        Console.Out.WriteLine(
            "A device with serial number {0} has been removed!",
            serialNumber);
    }
}

// Device event — configure ExposureEnd notification
cam.EventSelector.Value = EventSelectorEnums.EventExposureEnd.ToString();
cam.EventNotification.Value = EventNotificationEnums.On.ToString();

// After registering on the camera, OnDeviceEvent is called when ExposureEnd fires
class ManagedDeviceEventHandler : ManagedDeviceEvent
{
    protected override void OnDeviceEvent(string eventName)
    {
        Console.Out.WriteLine(
            "Got Device Event with Name=" + eventName + " and ID= {0}",
            GetDeviceEventId());
    }
}

Grabbing Images

Use GetNextImage() to retrieve images. Always release the image pointer when done — the managed image pointer is automatically released when set to null or when it goes out of scope.

// Begin capturing images
cam.BeginAcquisition();

// Retrieve an image
ManagedImage rawImage = cam.GetNextImage();

// Release image
rawImage.Release();

Check whether the grabbed image contains errors:

ImageStatus imageStatus = rawImage.ImageStatus;

Error Handling

Spinnaker C# uses SpinnakerException for exception handling:

try
{
    cam.Init();
}
catch (SpinnakerException ex)
{
    // Handle exception
}

Chunk Data

Chunk data allows the camera to append metadata (frame counter, width, height, exposure time, etc.) to each image.

// Enable chunk data for ExposureTime
cam.ChunkSelector.Value = ChunkSelectorEnums.ExposureTime.ToString();
cam.ChunkEnable.Value = true;
cam.ChunkModeActive.Value = true;

// Retrieve chunk data from an acquired image
String currentExposure = rawImage.ChunkData.ExposureTime.ToString();

Logging

Spinnaker supports five logging levels: Error, Warn, Notice, Info, and Debug. Levels are inclusive — monitoring Debug also captures all levels above it. By default, SpinView saves logs to C:\ProgramData\Spinnaker\Logs.

// Register logging callback class
LogCallbackHandler callBackClass = new LogCallbackHandler();
system.RegisterLoggingEvent(callBackClass);

// Set callback priority level
system.SetLoggingEventPriorityLevel(LoggingLevel);

class LogCallbackHandler : ManagedLoggingEventHandler
{
    public override void OnLogEvent(ManagedLoggingEvent loggingEvent)
    {
        // Process log event
    }
}

Design Conventions

Disposal Pattern

ManagedSystem, IManagedCamera, and IManagedImage wrap native C++ handles and implement IDisposable. Always use using blocks or explicitly call .Dispose() — do not rely on the GC to release native resources:

using var system = new ManagedSystem();
using var cameras = system.GetCameras();

IManagedCamera cam = cameras[0];
cam.Init();
try
{
    cam.BeginAcquisition();
    // ... acquire ...
    cam.EndAcquisition();
}
finally
{
    cam.Dispose();
}

Event Handling

The .NET API exposes camera and system events as strongly-typed registrations. Implement a handler class and register it before acquisition:

public class MyImageHandler : ManagedImageEventHandler
{
    override public void OnImageEvent(IManagedImage image)
    {
        Console.WriteLine($"Frame: {image.Width}x{image.Height}");
    }
}

var handler = new MyImageHandler();
cam.RegisterEvent(handler);
cam.BeginAcquisition();
// ... handler fires on each frame ...
cam.EndAcquisition();
cam.UnregisterEvent(handler);

Error Handling

The .NET API throws SpinnakerException on failure, compatible with standard .NET Exception patterns:

try
{
    cam.BeginAcquisition();
}
catch (SpinnakerException ex)
{
    Console.WriteLine($"Acquisition failed: {ex.Message}");
}

Quick Reference

System & Discovery

Class / Method Description
ManagedSystem System singleton — entry point for the SDK
ManagedSystem.GetCameras() Enumerate connected cameras
ManagedSystem.GetLibraryVersion() Query SDK version at runtime

Camera Lifecycle

Class / Method Description
ManagedCameraList Enumerable list of detected cameras
IManagedCamera Camera interface for configuration and acquisition
IManagedCamera.Init() Initialize the camera and populate node map
IManagedCamera.DeInit() De-initialize the camera
IManagedCamera.BeginAcquisition() Start image acquisition
IManagedCamera.EndAcquisition() Stop image acquisition

Image Handling

Class / Method Description
IManagedImage Captured image with pixel data access
IManagedImage.IsIncomplete Check for dropped or incomplete frame
IManagedImage.Width / Height Image dimensions in pixels
IManagedImage.PixelFormat Current pixel format
IManagedImage.Release() Return image to acquisition buffer pool
ManagedImageProcessor Image format conversion utility
ManagedImageProcessor.Convert() Convert to a different pixel format

Node Map & Configuration

Class / Method Description
IManagedCamera.GetNodeMap() Access GenICam node map (requires Init())
IManagedCamera.GetTLDeviceNodeMap() Transport layer device node map (pre-Init())
IManagedCamera.GetTLStreamNodeMap() Transport layer stream node map
IManagedNodeMap GenICam node map access for camera configuration
IInteger / IFloat / IBoolean / IEnumeration Typed GenICam node interfaces

Events & Callbacks

Class Description
ManagedImageEventHandler Base class for image arrival callbacks
ManagedDeviceEventHandler Base class for device-level events
ManagedLoggingEventHandler Base class for SDK log message callbacks
IManagedCamera.RegisterEvent() Attach an event handler to a camera
IManagedCamera.UnregisterEvent() Detach an event handler

Exception Reference

The .NET API signals all errors by throwing SpinnakerException. It inherits from System.Exception and additionally exposes the SDK error code:

Member Description
Message Human-readable error description
ErrorCode Numeric SDK error code (spinError)
FileName Source file where the error originated
FunctionName Function name where the error originated
LineNumber Line number where the error originated
FullErrorMessage Concatenated full error details

Common error codes are listed in the C API Error Code Reference.


Known Issues & Limitations

Windows Only

The Spinnaker .NET API is supported on Windows only. For cross-platform deployments, use the C API or Python API.

Garbage Collection & Native Resources

The GC does not guarantee timely cleanup of native camera handles. Always use using blocks or explicit .Dispose() calls — do not rely on finalizers for camera or image objects.


Further Reading