Impact Acquire SDK C++
GenICamInterfaceLayout.legacy.cpp

The GenICamInterfaceLayout.legacy program is a legacy version of the GenICamInterfaceLayout.cpp example.

Note
This is a legacy version of GenICamInterfaceLayout.cpp only needed when working on a system with a non C++11 capable compiler (e.g. Visual Studio smaller than version 2013 or gcc smaller than version 4.8). For a detailed description please have a look on the modern version of this example. Even though the used C++ code is slightly different the general idea of the example is the same!
Source code
//
// @description: Example applications for Impact Acquire
// @copyright: Copyright (C) 2019 - 2023 Balluff GmbH
// @authors: APIs and drivers development team at Balluff GmbH
// @initial date: 2019-02-20
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,i
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#ifdef _MSC_VER // is Microsoft compiler?
# if _MSC_VER < 1300 // is 'old' VC 6 compiler?
# pragma warning( disable : 4786 ) // 'identifier was truncated to '255' characters in the debug information'
# endif // #if _MSC_VER < 1300
#endif // #ifdef _MSC_VER
#include <iostream>
#include <apps/Common/exampleHelper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
# include <windows.h>
# include <process.h>
# include <mvDisplay/Include/mvIMPACT_acquire_display.h>
#else
# include <stdio.h>
# include <unistd.h>
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
using namespace std;
using namespace mvIMPACT::acquire;
static bool s_boTerminated = false;
//-----------------------------------------------------------------------------
struct ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev;
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
ImageDisplayWindow displayWindow;
explicit ThreadParameter( Device* p, const std::string& windowTitle ) : pDev( p ), displayWindow( windowTitle ) {}
#else
explicit ThreadParameter( Device* p ) : pDev( p ) {}
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
};
//-----------------------------------------------------------------------------
unsigned int DMR_CALL liveThread( void* pData )
//-----------------------------------------------------------------------------
{
ThreadParameter* pThreadParameter = reinterpret_cast<ThreadParameter*>( pData );
// establish access to the statistic properties
Statistics statistics( pThreadParameter->pDev );
// create an interface to the device found
FunctionInterface fi( pThreadParameter->pDev );
// Send all requests to the capture queue. There can be more than 1 queue for some devices, but for this sample
// we will work with the default capture queue. If a device supports more than one capture or result
// queue, this will be stated in the manual. If nothing is mentioned about it, the device supports one
// queue only. This loop will send all requests currently available to the driver. To modify the number of requests
// use the property mvIMPACT::acquire::SystemSettings::requestCount at runtime or the property
// mvIMPACT::acquire::Device::defaultRequestCount BEFORE opening the device.
TDMR_ERROR result = DMR_NO_ERROR;
while( ( result = static_cast<TDMR_ERROR>( fi.imageRequestSingle() ) ) == DMR_NO_ERROR ) {};
if( result != DEV_NO_FREE_REQUEST_AVAILABLE )
{
cout << "'FunctionInterface.imageRequestSingle' returned with an unexpected result: " << result
<< "(" << ImpactAcquireException::getErrorCodeAsString( result ) << ")" << endl;
}
manuallyStartAcquisitionIfNeeded( pThreadParameter->pDev, fi );
// run thread loop
int requestNr = INVALID_ID;
unsigned int cnt = 0;
const unsigned int timeout_ms = 500;
// we always have to keep at least 2 images as the display module might want to repaint the image, thus we
// cannot free it unless we have a assigned the display to a new buffer.
int lastRequestNr = INVALID_ID;
while( !s_boTerminated )
{
// wait for results from the default capture queue
requestNr = fi.imageRequestWaitFor( timeout_ms );
if( fi.isRequestNrValid( requestNr ) )
{
const Request* pRequest = fi.getRequest( requestNr );
if( pRequest->isOK() )
{
// within this scope we have a valid buffer of data that can be an image or any other
// chunk of data.
++cnt;
// here we can display some statistical information every 100th image
if( cnt % 100 == 0 )
{
cout << "Info from " << pThreadParameter->pDev->serial.read()
<< ": " << statistics.framesPerSecond.name() << ": " << statistics.framesPerSecond.readS()
<< ", " << statistics.errorCount.name() << ": " << statistics.errorCount.readS()
<< ", " << statistics.captureTime_s.name() << ": " << statistics.captureTime_s.readS() << endl;
}
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
pThreadParameter->displayWindow.GetImageDisplay().SetImage( pRequest );
pThreadParameter->displayWindow.GetImageDisplay().Update();
#else
cout << "Image captured(" << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << ")" << endl;
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
if( fi.isRequestNrValid( lastRequestNr ) )
{
// this image has been displayed thus the buffer is no longer needed...
fi.imageRequestUnlock( lastRequestNr );
}
lastRequestNr = requestNr;
// send a new image request into the capture queue
fi.imageRequestSingle();
}
else
{
// If the error code is -2119(DEV_WAIT_FOR_REQUEST_FAILED), the documentation will provide
// additional information under TDMR_ERROR in the interface reference
cout << "imageRequestWaitFor failed (" << requestNr << ", " << ImpactAcquireException::getErrorCodeAsString( requestNr ) << ")"
<< ", timeout value too small?" << endl;
}
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__APPLE__)
s_boTerminated = waitForInput( 0, STDOUT_FILENO ) == 0 ? false : true; // break by STDIN
#endif // #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__APPLE__)
}
manuallyStopAcquisitionIfNeeded( pThreadParameter->pDev, fi );
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
// stop the display from showing freed memory
pThreadParameter->displayWindow.GetImageDisplay().RemoveImage();
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
// In this sample all the next lines are redundant as the device driver will be
// closed now, but in a real world application a thread like this might be started
// several times an then it becomes crucial to clean up correctly.
// free the last potentially locked request
if( fi.isRequestNrValid( requestNr ) )
{
fi.imageRequestUnlock( requestNr );
}
// clear all queues
fi.imageRequestReset( 0, 0 );
return 0;
}
//-----------------------------------------------------------------------------
// This function will allow to select devices that support the GenICam interface
// layout(these are devices, that claim to be compliant with the GenICam standard)
// and that are bound to drivers that support the user controlled start and stop
// of the internal acquisition engine. Other devices will not be listed for
// selection as the code of the example relies on these features in the code.
bool isDeviceSupportedBySample( const Device* const pDev )
//-----------------------------------------------------------------------------
{
if( !pDev->interfaceLayout.isValid() &&
{
return false;
}
vector<TDeviceInterfaceLayout> availableInterfaceLayouts;
pDev->interfaceLayout.getTranslationDictValues( availableInterfaceLayouts );
return find( availableInterfaceLayouts.begin(), availableInterfaceLayouts.end(), dilGenICam ) != availableInterfaceLayouts.end();
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr, isDeviceSupportedBySample );
if( !pDev )
{
cout << "Unable to continue! Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
try
{
cout << "Initialising the device. This might take some time..." << endl << endl;
pDev->interfaceLayout.write( dilGenICam ); // This is also done 'silently' by the 'getDeviceFromUserInput' function but your application needs to do this as well so state this here clearly!
pDev->open();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while opening device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
try
{
// now display some SFNC(Standard Features Naming Convention) compliant features(see http://www.emva.org to find out more
// about the standard and to download the latest SFNC document version)
//
// IMPORTANT:
//
// The SFNC unfortunately does NOT define numerical values for enumerations, thus a device independent piece of software
// should use the enum-strings defined in the SFNC to ensure interoperability between devices. This is slightly slower
// but should not cause problems in real world applications. When the device type AND GenICam XML file version is
// guaranteed to be constant for a certain version of software, the driver internal code generator can be used to create
// and interface header, that has numerical constants for enumerations as well. Refer to the code generator chapter in
// the C++ documentation under 'Use Cases' for details.
displayPropertyDataWithValidation( dc.deviceVendorName, "DeviceVendorName" );
cout << endl;
displayPropertyDataWithValidation( dc.deviceModelName, "DeviceModelName" );
cout << endl;
// show the current exposure time allow the user to change it
displayAndModifyPropertyDataWithValidation( ac.exposureTime, "ExposureTime" );
// show the current pixel format, width and height and allow the user to change it
displayAndModifyPropertyDataWithValidation( ifc.pixelFormat, "PixelFormat" );
displayAndModifyPropertyDataWithValidation( ifc.width, "Width" );
displayAndModifyPropertyDataWithValidation( ifc.height, "Height" );
// start the execution of the 'live' thread.
cout << "Press [ENTER] to end the application" << endl;
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
unsigned int dwThreadID;
string windowTitle( "mvIMPACT_acquire sample, Device " + pDev->serial.read() );
// initialise display window
// IMPORTANT: It's NOT safe to create multiple display windows in multiple threads!!!
ThreadParameter threadParam( pDev, windowTitle );
HANDLE hThread = ( HANDLE )_beginthreadex( 0, 0, liveThread, ( LPVOID )( &threadParam ), 0, &dwThreadID );
cin.get();
s_boTerminated = true;
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
#else
ThreadParameter threadParam( pDev );
liveThread( &threadParam );
#endif // #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while operating the device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
return 0;
}
bool isValid(void) const
Checks if the internal component referenced by this object is still valid.
Definition: mvIMPACT_acquire.h:1606
Grants access to devices that can be operated by this software interface.
Definition: mvIMPACT_acquire.h:6990
This class and its functions represent an actual device detected by this interface in the current sys...
Definition: mvIMPACT_acquire.h:5951
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition: mvIMPACT_acquire.h:6383
void open(void)
Opens a device.
Definition: mvIMPACT_acquire.h:6252
PropertyIDeviceInterfaceLayout interfaceLayout
An enumerated integer property which can be used to define which interface layout shall be used when ...
Definition: mvIMPACT_acquire.h:6476
PropertyIAcquisitionStartStopBehaviour acquisitionStartStopBehaviour
An enumerated integer property defining the start/stop behaviour during acquisition of this driver in...
Definition: mvIMPACT_acquire.h:6621
ZYX read(int index=0) const
Reads a value from a property.
Definition: mvIMPACT_acquire.h:4173
const EnumPropertyI & getTranslationDictValues(std::vector< ZYX > &sequence) const
This function queries a list of valid values for this property.
Definition: mvIMPACT_acquire.h:4139
const EnumPropertyI & write(ZYX value, int index=0) const
Writes one value to the property.
Definition: mvIMPACT_acquire.h:4299
The function interface to devices supported by this interface.
Definition: mvIMPACT_acquire.h:10473
Category for the acquisition and trigger control features.
Definition: mvIMPACT_acquire_GenICam.h:2098
Category for device information and control.
Definition: mvIMPACT_acquire_GenICam.h:82
Category for Image Format Control features.
Definition: mvIMPACT_acquire_GenICam.h:1132
A base class for exceptions generated by Impact Acquire.
Definition: mvIMPACT_acquire.h:251
std::string getErrorCodeAsString(void) const
Returns a string representation of the error associated with the exception.
Definition: mvIMPACT_acquire.h:283
std::string read(int index=0) const
Reads a value from a property.
Definition: mvIMPACT_acquire.h:5162
std::string readS(int index=0, const std::string &format="") const
Reads data from this property as a string.
Definition: mvIMPACT_acquire.h:3216
Contains information about a captured buffer.
Definition: mvIMPACT_acquire.h:8449
PropertyI imageHeight
An integer property (read-only) containing the height of the image in pixels.
Definition: mvIMPACT_acquire.h:10050
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition: mvIMPACT_acquire.h:9224
PropertyIRequestResult requestResult
An enumerated integer property (read-only) defining the result of this request.
Definition: mvIMPACT_acquire.h:9530
PropertyI imageWidth
An integer property (read-only) containing the width of the image in pixels.
Definition: mvIMPACT_acquire.h:10039
Contains basic statistical information.
Definition: mvIMPACT_acquire.h:14201
A class that can be used to display images in a window.
Definition: mvIMPACT_acquire_display.h:585
TDMR_ERROR
Errors reported by the device manager.
Definition: mvDriverBaseEnums.h:2591
const int INVALID_ID
A constant to check for an invalid ID returned from the property handling module.
Definition: mvPropHandlingDatatypes.h:62
This namespace contains classes and functions that can be used to display images.
This namespace contains classes and functions belonging to the image acquisition module of this SDK.
Definition: mvCommonDataTypes.h:30