CPP API Manual

Introduction to the API

The C++ API has an elaborate class architecture. It is designed as a highly efficient and sophisticated API for advanced object-oriented programming including the STL (standard template library), shared pointers, and interface classes. If you prefer an API with less design patterns, we recommend using the C API.

See also

To understand the API, read the SDK Manual first: It contains essential information.

Tip

For more information about design patterns, we recommend the book Design Patterns. Elements of Reusable Object-Oriented Software.

To get the best possible performance, you need knowledge about multithreading. We recommend the book C++ Concurrency in Action.

Compatibility

The C++ API release build is compatible with Visual Studio 2017. If you use a higher version, we recommend you to rebuild the C++ API by compiling the source files with your Visual Studio version. You can also use other IDEs that implement the C++11 standard (or higher) if you compile the C++ API source files with these IDEs.

C++ API diagram

The image below shows a simplified C++ API UML diagram. To ease understanding the concept, only the most important items are listed. For classes that you access through their pointers, the diagram shows these pointers instead of the corresponding class names.

Simplified UML diagram

Simplified UML diagram

Shared pointers

General aspects

A shared pointer is an object that wraps any regular pointer variable to control its lifetime. Besides wrapping the underlying raw pointer, it keeps track of the number of copies of itself. By doing so, it ensures that it will not release the wrapped raw pointer until its reference count (the number of copies) has dropped to zero. A shared pointer automatically deletes the wrapped pointer when the last shared pointer to it is destroyed. Though giving away the responsibility for deallocation, the programmer can still work on the very same objects.

Because of the mentioned advantages, the C++ API makes heavy use of shared pointers while not relying on a specific implementation.

Shared pointers code snippet
{
  // This declares an empty shared pointer that can wrap a pointer of
  // type Camera
  CameraPtr sp1;

  // The reset member function tells the shared pointer to
  // wrap the provided raw pointer
  // sp1 now has a reference count of 1
  sp1.reset( new Camera () );
  {
      // In this new scope we declare another shared pointer
      CameraPtr sp2;

      // By assigning sp1 to it the reference count of both (!) is set to 2
      sp2 = sp1;
  }
  // When sp2 goes out of scope the reference count drops back to 1
}
// Now that sp1 has gone out of scope its reference count has dropped
// to 0 and it has released the underlying raw pointer on destruction

Replacing the shared pointer library

Although it is best practice to use the predefined shared pointer type, you can replace it with a different pointer type from libraries like Qt or Boost. In order to ease this exchange, the VmbCPP source files include the header file UserSharedPointerDefines.h. This header file also lists the needed template functions and typedefs. Additionally, the table below lists template parameters covering the basic functionality that Vimba X expects from any shared pointer. Since a shared pointer is a generic type, it requires a template parameter. That is what the various typedefs are for. For example, the CameraPtr is just an alias for VmbCPP::SharedPointer< VmbCPP::Camera>.

To replace the shared pointers, follow these steps:

  1. Add UserSharedPointerDefines.h by adding the define USER_SHARED_POINTER to your compiler settings.

  2. Add your shared pointer source files to the C++ API project.

  3. Define the template parameters and typedefs as described in the header UserSharedPointerDefines.h.

  4. Recompile the C++ API.

Vimba X now is ready to use the added shared pointer implementation without changing its behavior. Within your own application, you can employ your shared pointers as usual. Note that your application and Vimba X must refer to the same shared pointer type.

Tip

If you want your application to substitute its shared pointer type along with Vimba X, you can use the template parameters listed in the table below in your application as well.

Function

Example

Purpose

n/a

VmbCPP::SharedPointer<MyClass>
mySharedPointer;

Declares new shared
pointer

SP_SET( sp, rawPtr )

VmbCPP::SP_SET(mySharedPointer, rawPtr);

Tells existing pointer
to wrap given raw pointer

SP_RESET( sp )

VmbCPP::SP_RESET(mySharedPointer);

Tells existing pointer
to decrease reference count

SP_ISEQUAL( sp1, sp2 )

VmbCPP::SP_ISEQUAL(mySharedPointer,
mySharedPointer2)

Checks addresses of wrapped
raw pointers for equality

SP_ISNULL( sp )

VmbCPP::SP_ISNULL(mySharedPointer)

Checks address of wrapped
raw pointer for NULL

SP_ACCESS( sp )

MyClass* rawPtr =
VmbCPP::SP_ACCESS(mySharedPointer);

Returns wrapped raw pointer

SP_DYN_CAST<TargetType,
SourceType> ( sp )

VmbCPP::SharedPointer<MyDerivedClass> derived
= VmbCPP::SP_DYN_CAST<MyDerivedClass,
MyClass>(mySharedPointer);

Dynamic cast of the
pointer

API usage

Entry point

The entry point to the C++ API is the VmbSystem singleton. To obtain a reference to it, call the static function VmbSystem::GetInstance. All C++ classes reside in the namespace VmbCPP, so employ the using declaration using VmbCPP.

API version

Even if new features are introduced to the C++ API, your software remains backward compatible. Use VmbSystem::QueryVersion to check the version number of the API. You can run this function without initializing the API.

API startup and shutdown

To start and shut down the C++ API, use these paired functions:

  • VmbSystem::Startup() initializes the API, the TLs, and Interfaces. With the optional parameter pathConfiguration, you can select which transport layers are used.

  • VmbSystem::Shutdown() shuts down the API and destroys all used objects in the API (when all observers have finished execution).

VmbSystem::Startup and VmbSystem::Shutdown must always be paired. Calling the pair several times within the same program is possible, but not recommended. Successive calls of VmbSystem::Startup or VmbSystem::Shutdown are ignored and the first VmbSystem::Shutdown after a VmbSystem::Startup closes the API.

Note

Always shut down the API when your application closes. Shutting down the API is necessary under all circumstances to unload the transport layers. If they still are loaded although the application is closed, they access invalid memory.

Note

VmbSystem::Shutdown blocks until all callbacks have finished execution.

Listing cameras

The function VmbSystem::GetCameras enumerates all cameras recognized by the underlying transport layers. With this command, you can fetch the list of all connected camera objects. Before opening cameras, camera objects contain all static details of a physical camera that do not change throughout the object’s lifetime such as the camera id and the camera model.

The order in which the detected cameras are listed is determined by the order of camera discovery and therefore not deterministic. Moreover, the order may change depending on your system configuration and the accessories (for example, hubs or long cables).

GigE cameras

For GigE cameras, discovery has to be initiated by the host software. This is done automatically if you register a camera list observer of type ICameraListObserv with VmbSystem.

In this case, a call to VmbSystem::GetCameras or VmbSystem::GetCameraByID returns immediately. If no camera list observer is registered, a call to VmbSystem::GetCameras or VmbSystem::GetCameraByID takes some time because the responses to the initiated discovery command must be waited for.

USB cameras

Changes to the plugged cameras are detected automatically. Consequently, any changes to the camera list are announced via discovery events and the call to VmbSystem::GetCameras returns immediately.

MIPI CSI cameras

Cameras with MIPI CSI-2 interface are detected when the board is booted. To avoid damage to the hardware, do not plug in or out a camera while the board is powered.

Getting the camera list code snippet
std::string name;
CameraPtrVector cameras;
VmbSystem &system = VmbSystem::GetInstance();
if( VmbErrorSuccess == system.Startup() )
{
    if( VmbErrorSuccess == system.GetCameras( cameras ) )
    {
        for( CameraPtrVector::iterator iter = cameras.begin();
              cameras.end() != iter;
              ++iter )
        {
             if( VmbErrorSuccess == (*iter)->GetName( name ) )
             {
              std::cout << name << std::endl;
             }
        }
    }
}
Basic functions of the Camera class

Function
returning VmbErrorType

Purpose

GetID( std::string& ) const

Unique ID

GetName( std::string& ) const

Name

GetModel( std::string& ) const

Model name

GetSerialNumber( std::string& ) const

Serial number

GetPermittedAccess( VmbAccessModeType& ) const

Mode to open the camera

GetInterfaceID( std::string& ) const

ID of the interface the camera is connected to

The following table lists additional functions of the Camera class.

Additional functions of the Camera class

Camera class member functions

Comment

GetInterface()

Access the Interface and its features

GetTransportLayer()

Access the TL and its features

GetLocalDevice()

Access local device features

GetStreams()

Enumerate camera streams

GetExtendedID()

Get the Extended ID (if available)

GetLocalDevice()

Access local device features

Extended ID

Tip

In most cases, the Extended ID is not needed. can use it as needed.

If several TLs are available for one camera, the camera is listed several times. To avoid potential conflicts, the SDK automatically creates an extended ID string for each camera. extended ID string is provided in the struct VmbCameraInfo_t: cameraIdStringExtended.

Extended IDs use the following grammar:

extended_id : <tl_identifier-char-count> separator tl_identifier <interface_id-char-count>
separator interface_id <camera_id-char-count> separator camera_id separator   : ':'`

Note

Extended IDs always overwrite other ids. A non-extended ID may be unusable after other cameras are discovered.

Extended IDs

Placeholder

Description

tl_identifier

File path of the transport layer

interface_id

ID of the interface as reported by the transport layer

camera_id

Camera (non-extended) ID as reported by the interface

<tl_identifier-char-count>

Number of characters (TL ID) encoded as decimal integer

<interface_id-char-count>

Number of characters (interface ID) encoded as decimal integer

<camera_id-char-count>

Number of characters encoded as decimal integer

Notifications of changed camera states

For being notified whenever a camera is detected, disconnected, or changes its open state, use VmbSystem::RegisterCameraListObserver (GigE and USB only). This call registers a camera list observer (of type ICameraListObserver) with the VmbSystem that gets executed on the according event. The observer function to be registered has to be of type ICameraListObserver*.

Note

Functions that must not be called within your camera list observer:

  • VmbSystem::Startup

  • VmbSystem::Shutdown

  • VmbSystem::GetCameras

  • VmbSystem::GetCameraByID

  • VmbSystem::RegisterCameraListObserver

  • VmbSystem::UnregisterCameraListObserver

  • Feature::SetValue

  • Feature::RunCommand

Opening and closing a camera

A camera must be opened to control it and to capture images. Call Camera::Open with the camera list entry of your choice, or use function VmbSystem::OpenCameraByID with the ID of the camera. In both cases, also provide the desired access mode for the camera.

The API provides several access modes:

  • VmbAccessModeFull: read and write access. Use this mode to configure the camera features and to acquire images (Goldeye CL cameras: configuration only).

  • VmbAccessModeRead: read-only access. Setting features is not possible. However, for GigE cameras that are already in use by another application, the acquired images can be transferred to the API(Multicast).

Open cameras code snippet
CameraPtrVector cameras;
VmbSystem &system = VmbSystem::GetInstance();

if( VmbErrorSuccess == system.Startup() )
{
    if( VmbErrorSuccess == system.GetCameras( cameras ) )
    {
        for( CameraPtrVector::iterator iter = cameras.begin();
              cameras.end() != iter;
              ++iter )
        {
            if( VmbErrorSuccess == (*iter)->Open( VmbAccessModeFull ) )
            {
                std::cout << "Camera opened" << std::endl;
            }
        }
    }
}

The following code snippet shows how to open a GigE camera by its IP address. Opening the camera by its serial number or MAC address is also possible.

Open Camera by IP code snippet
CameraPtr camera;
VmbSystem &system = VmbSystem::GetInstance();
if( VmbErrorSuccess == system.Startup() )
{
    if( VmbErrorSuccess == system.OpenCameraByID( "192.168.0.42",
                                                 VmbAccessModeFull ,
                                                 camera ) )
    {
        std::cout << "Camera opened" << std::endl;
    }
}

The following code snippet shows how to close a camera using Camera::Close.

Closing a camera code snippet
// The "camera" object points to an opened camera
if( VmbErrorSuccess == camera.Close() )
{
    std::cout << "Camera closed" << std::endl;
}

Accessing features

The function Camera::Open provides access to the features of the Remote Device module. To access features of the interface, you can retrieve the pointer to the Interface instance via member function Camera::GetInterface(), similar for accessing the features of the Transport Layer module.

Feature types

The C++ API provides several feature types, which all have their specific properties and functionalities. The API provides its own set of access functions for every feature data type.

Functions for reading and writing a feature

Type

Set

Get

Range/Increment

Enum

SetValue( string )

GetValue( string& )

GetValues( StringVector& )

SetValue( int )

GetValue( int& )

GetValues( IntVector& )

GetEntry( EnumEntry& )

GetEntries( EntryVector& )

Int

SetValue( int )

GetValue( int& )

GetRange( int&, int& )

GetIncrement( int& )

Float

SetValue( double )

GetValue( double& )

GetRange( double&, double& )

GetIncrement( double& )

String

SetValue( string )

GetValue( string& )

Bool

SetValue( bool )

GetValue( bool& )

Command

RunCommand( )

IsCommandDone( bool& )

Raw

SetValue( uchar )

GetValue( UcharVector& )

With the member function GetValue, a feature’s value can be queried. With the member function SetValue, a feature’s value can be set.

Integer and double features support GetRange. These functions return the minimum and maximum value that a feature can have. Integer features also support the GetIncrement function to query the step size of feature changes. Valid values for integer features are min <= val <= min + [(max-min)/increment] * increment (the maximum value might not be valid).

Enumeration features support GetValues that returns a vector of valid enumerations as strings or integers. These values can be used to set the feature according to the result of IsValueAvailable. If a non-empty vector is supplied, the original content is overwritten and the size of the vector is adjusted to fit all elements. An enumeration feature can also be used in a similar way as an integer feature.

Since not all the features are available all the time, the current accessibility of features may be queried via IsReadable() and IsWritable(), and the availability of Enum values can be queried with IsValueAvailable( string ) or IsValueAvailable( int ) .

With Camera::GetFeatures, you can list all features available for a camera. This list remains static while the camera is opened. The Feature class of the entries in this list also provides information about the features that always stay the same for this camera. Use the member functions of class Feature to access them as shown in the following code snippets:

Reading a camera feature code snippet
FeaturePtr feature;
VmbInt64_t width;

if( VmbErrorSuccess == camera->GetFeatureByName( "Width", feature )
{
    if( VmbErrorSuccess == feature->GetValue( width ) )
    {
        std::out << width << std::endl;
    }
}

Writing features to a camera and running a command feature:

Writing features and running command features
FeaturePtr feature;

if( VmbErrorSuccess == camera->GetFeatureByName( "AcquisitionMode", feature )
{
    if( VmbErrorSuccess == feature->SetValue( "Continuous" ) )
    {
        if( VmbErrorSuccess == camera->GetFeatureByName( "AcquisitionStart",
                                                           feature ) )
        {
            if( VmbErrorSuccess == feature->RunCommand() )
            {
                std::out << "Acquisition started" << std::endl;
            }
        }
    }
}

The following table introduces the basic features of all cameras. A feature has a name, a type, and access flags such as read-permitted and write-permitted. To get notified when a feature’s value changes use Feature::RegisterObserver (see section Using Events). The observer to be registered has to implement the interface IFeatureObserver. This interface declares the member function FeatureChanged. In the implementation of this function, you can react on updated feature values as it will get called by the API on the according event.

Functions for accessing static properties of a feature

Function
returning VmbErrorType

Purpose

GetName( std::string& )

Name of the feature

GetDisplayName( std::string& )

Name to display in GUI

GetDataType( VmbFeatureDataType& )

Data type of the feature. Gives information
about the available functions for the feature.

GetFlags( VmbFeatureFlagsType& )

Static feature flags, containing information
about the actions available for a feature:
Read an Write, Volatile (changes with every
Read possible). ModifyWrite features are ajdusted to
valid values.

GetCategory( std::string& )

Category the feature belongs to, used for
structuring the features

GetPollingTime( VmbUint32_t& )

The suggested time to poll the feature

GetUnit( std::string& )

The unit of the feature, if available

GetRepresentation( std::string& )

The scale to represent the feature, used
as a hint for feature control

GetVisibility( VmbFeatureVisibilityType& )

The audience the feature is for

GetToolTip( std::string& )

Short description of the feature, used
for bubble help

GetDescription( std::string& )

Description of the feature, used
as extended explanation

GetSFNCNamespace( std::string& )

The SFNC namespace of the feature

GetAffectedFeatures( FeaturePtrVector& )

Features that change if the feature is changed

GetSelectedFeatures( FeaturePtrVector& )

Features that are selected by the feature

Functions for accessing static properties of a feature

Feature

Type

Access

Description

AcquisitionMode

Enumeration

R/W

Values: Continuous,
SingleFrame, MultiFrame.

AcquisitionStart

Command

Start acquiring images.

AcquisitionStop

Command

Stop acquiring images.

PixelFormat

Enumeration

R/W

Image format (Mono8 etc.)

Width

Uint32

R/W

Image width, in pixels.

Height

Uint32

R/W

Image height, in pixels.

PayloadSize

Uint32

R

Use VmbPayloadSizeGet()

Note

Functions that must not be called within the feature observer:

  • VmbSystem::Startup

  • VmbSystem::Shutdown

  • VmbSystem::GetCameras

  • VmbSystem::GetCameraByID

  • VmbSystem::RegisterCameraListObserver

  • VmbSystem::UnregisterCameraListObserver

  • Feature::SetValue

  • Feature::RunCommand

Acquiring images

See also

The SDK Manual describes synchronous and asynchronous image acquisition.

Image Capture vs. Image Acquisition

Image capture and image acquisition are two independent operations: The API captures images, the camera acquires images. To obtain an image from your camera, setup the API to capture images before starting the acquisition on the camera:

Typical asynchronous application using VmbCPP

Typical asynchronous application using VmbCPP

Asynchronous image acquisition

The following code snippet is a minimalistic example of asynchrounous image acquisition.

Simple image streaming code snippet
#include "VmbCPP/VmbCpp.h"
using namespace VmbCPP;

// Constructor for the FrameObserver class
FrameObserver :: FrameObserver(CameraPtr pCamera) : IFrameObserver(pCamera ){}

// Frame callback notifies about incoming frames
void FrameObserver::FrameReceived(const FramePtr pFrame)
{
   // Send notification to working thread
   // Do not apply image processing within this callback (performance)
   // When the frame has been processed, requeue it
   m_pCamera ->QueueFrame(pFrame );
}

int main()
{
   VmbInt64_t nPLS; // Payload size value
   FeaturePtr pFeature; // Generic feature pointer
   VmbSystem &sys = VmbSystem::GetInstance (); // Create and get Vmb singleton
   CameraPtrVector cameras; // Holds camera handles
   CameraPtr camera;
   FramePtrVector frames (15); // Frame array

   // Start the API, get and open cameras
   sys.Startup();
   sys.GetCameras(cameras );
   camera = cameras[0];
   camera->Open( VmbAccessModeFull );

   // Get the image size for the required buffer
   // Allocate memory for frame buffer
   // Register frame observer/callback for each frame
   // Announce frame to the API
   camera->GetFeatureByName( "VmbPayloadsizeGet", pFeature );
   pFeature->GetValue(nPLS);
   for( FramePtrVector::iterator iter = frames.begin(); frames.end() != iter; ++iter)
   {
      (*iter).reset(new Frame(nPLS ));
      (*iter)->RegisterObserver(IFrameObserverPtr(new FrameObserver(camera )));
      camera->AnnounceFrame(*iter);
   }

   // Start the capture engine (API)
   camera ->StartCapture();
   for( FramePtrVector::iterator iter = frames.begin(); frames.end() != iter; ++iter)
   {
      // Put frame into the frame queue
      camera->QueueFrame(*iter);
   }

       // Start the acquisition engine (camera)
   camera->GetFeatureByName( "AcquisitionStart", pFeature );
   pFeature->RunCommand();

   // Program runtime , e.g., Sleep (2000);

   // Stop the acquisition engine (camera)
   camera->GetFeatureByName( "AcquisitionStop", pFeature );
   pFeature->RunCommand();

   // Stop the capture engine and discard all pending callbacks (API)
   // Flush the frame queue
   // Revoke all frames from the API
   camera->EndCapture ();
   camera->FlushQueue ();
   camera->RevokeAllFrames ();
   for( FramePtrVector::iterator iter = frames.begin(); frames.end() != iter; ++iter)
   {
      // Unregister the frame observer/callback
      (*iter)->UnregisterObserver();
   }
   camera->Close();
   sys.Shutdown(); // Always pair sys.Startup and sys.Shutdown
}

Image capture

To enable image capture, frame buffers must be allocated and the API must be prepared for incoming frames. This is done in convenience function Camera::StartContinuousAcquisition (Camera::StopContinuousAcquisition stops acquisition). Note that these convenience functions perform all steps shown in section Image Capture vs. Image Acquisition for each single image. Therefore, they do not provide best performance if your vision application requires frequently starting and stopping image acquisition. In this case, it is unnecessary to prepare image acquisisition and to clean up for each image. Instead, you can prepare image acquisition once, toggle between the start and stop functions, and clean up after your images are captured.

Optionally, you can activate the alloc and announce functionality for more efficient buffer allocation. To do this, use the optional parameter /x.

Note

CSI-2 cameras only:

We recommend using alloc and announce. If you want to use the announce mode with the CSI TL, without using the Convenience functions AcquireSingleImage(), AcquireMultipleImages(), and StartContinuousImageAcquisition(), make sure you pass the StreamBufferAlignment within the Frame Constructor.

Asynchronous image capture step by step:

  1. Open the camera as described in chapter Opening and closing a camera.

  2. Query the necessary buffer size through the convenience function VmbPayloadsizeGet(). Allocate frames of this size.

  3. Announce the frames.

  4. Start the capture engine.

  5. Queue the frame you have just created with Camera::QueueFrame, so that the buffer can be filled when the acquisition has started.

The API is now ready. Start and stop image acquisition on the camera as described in section Acquiring images.

Register a frame observer that gets executed when capturing is complete. The frame observer has to be of type IFrameObserver. Within the frame observer, queue the frame again after you have processed it.

  1. Stop the capture engine and discard all pending callbacks with Camera::EndCapture.

  2. Call Camera::FlushQueue to cancel all frames on the queue. If the API has done the memory allocation, this memory is not released until RevokeAllFrames, RevokeFrame, EndCapture, or Close functions have been called.

  3. Revoke the frames with Camera::RevokeAllFrames to clear the buffers.

To synchronously capture images (blocking your execution thread), follow these steps:

  1. Open the camera as described in section Opening and closing a camera.

  2. How you proceed depends on the number of frames and the performance you need:

    • Single frame: You can use the convenience function Camera::AcquireSingleImage to receive one image frame.

    • Multiple frames: You can use the convenience function Camera::AcquireMultipleImages to receive several image frames (determined by the size of your vector of FramePtrs).

Note

If your application requires a low CPU load or exact triggering, we recommend a different approach: Set the feature AcquisitionMode to MultiFrame or Continuous and run the command AcquisitionStart (see section Acquiring images).

To assure correct continuous image capture, use at least two or three frames. The appropriate number of frames to be queued in your application depends on the frames per second the camera delivers and on the speed with which you are able to re-queue frames (also taking into consideration the operating system load). The image frames are filled in the same order in which they were queued.

Note

Always check that Frame::GetReceiveStatus returns VmbFrameStatusComplete when a frame is returned to ensure the data is valid.

Note

Functions that must not be called within the frame observer:

  • VmbSystem::Startup

  • VmbSystem::Shutdown

  • VmbSystem::OpenCameraByID

  • Camera::Open

  • Camera::Close

  • Camera::AcquireSingleImage

  • Camera::AcquireMultipleImages

  • Camera::StartContinuousImageAcquisition

  • Camera::StopContinuousImageAcquisition

  • Camera::StartCapture

  • Camera::EndCapture

  • Camera::AnnounceFrame

  • Camera::RevokeFrame

  • Stream::Open

  • Stream::Close

  • Stream::AcquireSingleImage

  • Stream::AcquireMultipleImages

  • Stream::StartCapture

  • Stream::EndCapture

  • Stream::AnnounceFrame

  • Stream::RevokeFrame

  • Stream::RevokeAllFrames

Image Acquisition

If you have decided to use one of the convenience functions Camera::AcquireSingleImage, Camera::AcquireMultipleImages, or Camera::StartContinuousImageAcquisition, no further actions are necessary.

Only if you have setup capture step by step as described in section Image capture, you have to start image acquisition on your camera:

  1. Set the feature AcquisitionMode (for example, to Continuous).

  2. Run the command AcquisitionStart.

To stop image acquisition, run command AcquisitionStop. The code snippet below shows a simplified streaming example without error handling.

Image streaming code snippet
VmbErrorType err;           // Every Vimba X function returns an error code that
                            // should always be checked for VmbErrorSuccess
VmbSystem &sys;             // A reference to the VmbSystem singleton
CameraPtrVector cameras;    // A list of known cameras
FramePtrVector frames( 3 ); // A list of frames for streaming. We chose
                            // to queue 3 frames.
IFrameObserverPtr pObserver( new MyFrameObserver () ); // Our implementation
                                                       // of a frame observer
FeaturePtr pFeature;        // Any camera feature
VmbInt64_t nPLS;            // The payload size of one frame

sys = VmbSystem::GetInstance ();
err = sys.Startup ():
err = sys.GetCameras( cameras );
err = cameras [0]->Open( VmbAccessModeFull );
err = cameras [0]-> GetFeatureByName( "VmbPayloadsizeGet", pFeature ); (A)
err = pFeature ->GetValue( nPLS )                                      (A)

for ( FramePtrVector::iterator iter = frames.begin ();
      frames.end() != iter;
      ++iter )
{
    ( *iter ).reset( new Frame( nPLS ) );                              (B)
    err = ( *iter )->RegisterObserver( pObserver ) );                  (C)
    err = cameras[0]-> AnnounceFrame( *iter );                         (1)
}

err = cameras[0]-> StartCapture();                                     (2)

for ( FramePtrVector :: iterator iter = frames.begin ();
      frames.end() != iter;
      ++iter )
{
      err = cameras[0]->QueueFrame( *iter );                           (3)
}

err = GetFeatureByName( "AcquisitionStart", pFeature );                (4)
err = pFeature ->RunCommand();                                         (4)

// Program runtime ...
// When finished , tear down the acquisition chain , close camera and API

err = GetFeatureByName( "AcquisitionStop", pFeature );
err = pFeature ->RunCommand();
err = cameras [0]-> EndCapture();
err = cameras [0]-> FlushQueue();
err = cameras [0]-> RevokeAllFrames();
err = cameras [0]->Close();
err = sys.Shutdown();

Transforming images

To transform images received via the API into common image formats, use the Image Transform Library.

See also

For a quick start, see the AsynchrounousGrab example,

Using Events

Events serve a multitude of purposes and can have several origins such as VmbSystem,Interface, and Cameras

In the C++ API, notifications are issued as a result to a feature invalidation of either its value or its state. Consequently, to get notified about any feature change, register an observer of the desired type (ICameraListObserver, IInterfaceListObserver, or IFeatureObserver) with the appropriate RegisterXXXObserver method (RegisterCameraListObserver, RegisterInterfaceListObserver, or RegisterObserver), which gets called if there is a change to that feature.

Three examples are listed in this chapter:

  • Camera list notifications

  • Tracking invalidations of features

  • Explicit camera event features

For camera list notifications, see the code snippet below:

Getting notified about camera list changes
// 1. define observer that reacts on camera list changes
class CamObserver : public ICameraListObserver
{
...
public:
    void CameraListChanged( CameraPtr pCam , UpdateTriggerType reason )
    {
        // Next to the camera pointer a reason why the observer's function was triggered
        // is passed in. Possible values are:
        // UpdateTriggerPluggedIn (0), a new camera was discovered
        // UpdateTriggerPluggedOut (1), a known camera disappeared from the bus
        // UpdateTriggerOpenStateChanged (3), a known camera was opened or closed
        // by another application
        if( UpdateTriggerPluggedIn == reason || UpdateTriggerPluggedOut == reason )
        {
            // Put your code here to react on the changed camera list
            // E.g., by sending a Windows event message or
            // triggering a Qt or boost signal to update your view
        }
        else
        {
            // React on a changed open state
        }
    }
};

{
    VmbErrorType res;
    VmbSystem &sys = VmbSystem::GetInstance();
    FeaturePtr pFeature;

    // 2. Register the observer; automatic discovery for GigE is turned on
    res = sys.RegisterCameraListObserver( ICameraListObserverPtr( new CamObserver () ) );
}
Getting notified about feature list changes
// 1. define observer
class WidthObserver : public IFeatureObserver
{
...
public:
  void FeatureChanged( const FeaturePtr &feature )
   {
     if ( feature != NULL )
     {
       VmbError_t res;
       std:: string strName("");
       res = feature->GetDisplayName(strName );
       std::cout << strName << " changed" << std::endl;
     }
   }
};

{
    ...
    // 2. register the observer for the camera event
    res = GetFeatureByName( "EventAcquisitionStart", pFeature );
    res = pFeature->RegisterObserver( IFeatureObserverPtr( new EventObserver() ));

    // 3. select "AcquisitionStart" (or a different) event
    res = GetFeatureByName( "EventSelector", pFeature );
    res = pFeature->SetValue( "AcquisitionStart" );

    // 4. switch on the event notification (or switch it off with "Off")
    res = GetFeatureByName( "EventNotification", pFeature );
    res = pFeature->SetValue( "On" );
}
Getting notified about camera events
// 1. define observer
class EventObserver : public IFeatureObserver
{
...
public:
  void FeatureChanged ( const FeaturePtr &feature )
  {
    if ( feature != NULL )
    {
      VmbError_t res;
      std:: string strName("");

      res = feature ->GetDisplayName(strName );
      std::cout "Event " << strName << " occurred" << std::endl;
    }
  };

{
  ...
  // 2. register the observer for the camera event
  res = GetFeatureByName( "Width", pFeature );
  res = pFeature ->RegisterObserver( IFeatureObserverPtr( new WidthObserver () ));

  // As an example , binning is changed , so the observer will be run
  res = GetFeatureByName( "BinningHorizontal", pFeature );
  res = pFeature ->SetValue( "8" );

}

Chunk

Note

To use the chunk feature, make sure your camera supports it.

Chunk data are image metadata such as the exposure time that are available in the Frame. To activate chunk, see the user documentation of your camera.

To access the chunk feature, call Frame::AccessChunkData() from FrameObserver::FrameReceived(). Within this function, you can access chunk features via the FeatureContainerPtr.

See also

See the ChunkAccess example.

See also

For user defined error codes, see the code snippet in section Chunk in the C API Manual.

Saving and loading settings

Additionally to the user sets stored inside the cameras, you can save the feature values of the GenTL modules as an XML file to your host PC.

Saving and loading settings
VmbSystem &system = VmbSystem::GetInstance ();
CameraPtrVector cameras;

if ( VmbErrorSuccess == system.Startup () )
{
    if ( VmbErrorSuccess == system.GetCameras( cameras ) )
    {
        if (cameras.size() > 0)
        {
            CameraPtr cam = cameras[0];
            if ( VmbErrorSuccess == cam->Open(VmbAccessModeFull) )
            {
                std::filesystem::path xmlFile("camera_0_settings.xml");
                VmbFeaturePersistSettings_t settingsStruct;
                settingsStruct.loggingLevel = 1;
                settingsStruct.maxIterations = 5;
                settingsStruct.persistType = VmbFeaturePersistNoLUT;
                if (VmbErrorSuccess != pCam->SaveSettings( xmlFile, &settingsStruct ) )
                {
                    std::cout << "Could not save camera settings to '" << xmlFile << "'" << std::endl;
                }
                cam->Close();
            }
        }
    }
    system.Shutdown();
}

Logging levels:

  • 0: Info only

  • 1: With errors

  • 2: With warnings

  • 3: Debug

  • 4: Trace

Iterations: Several iterations may be needed to catch all feature dependencies (compare desired value with camera value and write it to camera).

To control which features are saved, see the C API Manual, chapter Saving and loading settings.

Triggering

Note

Before triggering, startup the API and open the camera(s).

External trigger

The following code snippet shows how to trigger your camera with an external device.

External trigger code snippet
// Startup the API, get cameras and open cameras as usual
// Trigger cameras according to their interface
// Configure trigger input line and selector , switch trigger on
( *iter )->GetInterfaceType( pinterface );
switch( pinterface )
{
   case VmbInterfaceEthernet:
   ( *iter )->GetFeatureByName( "TriggerSelector", pFeature );
   pFeature->SetValue( "FrameStart" );
   ( *iter )->GetFeatureByName( "TriggerSource", pFeature );
   pFeature->SetValue( "Line1" );
   ( *iter )->GetFeatureByName( "TriggerMode", pFeature );
   pFeature->SetValue( "On" );
   break;

   // USB: VmbInterfaceUsb
   // CSI-2: VmbInterfaceCSI2

   case VmbInterfaceUsb:
   ( *iter )->GetFeatureByName( "LineSelector", pFeature );
   pFeature->SetValue( "Line0" );
   ( *iter )->GetFeatureByName( "LineMode", pFeature );
   pFeature->SetValue( "Input" );
   ( *iter )->GetFeatureByName( "TriggerSource", pFeature );
   pFeature->SetValue( "Line0" );
   ( *iter )->GetFeatureByName( "TriggerMode", pFeature );
   pFeature->SetValue( "On" );
   break;
}

Listing interfaces

You can list all found interfaces such as frame grabbers or NICs. VmbSystem::GetInterfaces enumerates all interfaces recognized by the underlying transport layers.

Get interfaces code snippet
std:: string name;
InterfacePtrVector interfaces;
VmbSystem &system = VmbSystem::GetInstance();

if( VmbErrorSuccess == system.Startup() )
{
    if( VmbErrorSuccess == system.GetInterfaces( interfaces ) )
    {
        for( InterfacePtrVector::iterator iter = interfaces.begin();
              interfaces.end() != iter;
              ++iter )
        {
            if ( VmbErrorSuccess == (*iter)->GetName( name ) )
            {
                std::cout << name << std::endl;
            }
        }
    }
}

The Interface class provides the member functions to obtain information about an interface listed in the following table.

Basic functions of the Interface class

Function (returning VmbErrorType)

Purpose

GetID( std::string& ) const

The unique ID

GetName( std::string& ) const The name

The name

GetType( VmbInterfaceType& ) const

The camera interface type

GetSerialNumber( std::string& ) const

The serial number (not in use)

Error codes

For error codes and other technical issues, see Troubleshooting.