Impact Acquire SDK C++
ContinuousCaptureAllFormats.win32.cpp

The ContinuousCaptureAllFormats.win32 program is based on the ContinuousCapture.win32.cpp example.

Note
This is a Windows® version of ContinuousCaptureAllFormats.cpp only needed when working on a Windows® system with a non C++11 capable compiler (e.g. Visual Studio smaller then 2013). 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) 2005 - 2024 Balluff GmbH
// @authors: APIs and drivers development team at Balluff GmbH
// @initial date: 2005-03-15
//
// 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 <windows.h>
#include <process.h>
#include <iostream>
#include <apps/Common/exampleHelper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#include <mvDisplay/Include/mvIMPACT_acquire_display.h>
using namespace std;
using namespace mvIMPACT::acquire;
static bool s_boTerminated = false;
//-----------------------------------------------------------------------------
struct ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev;
ImageDisplayWindow dispConverted;
ThreadParameter( Device* p, const string& windowTitle ) : pDev( p ), dispRaw( windowTitle ), dispConverted( windowTitle + "(converted)" ) {}
};
//-----------------------------------------------------------------------------
unsigned int __stdcall liveThread( void* pData )
//-----------------------------------------------------------------------------
{
ThreadParameter* pThreadParameter = reinterpret_cast<ThreadParameter*>( pData );
unsigned int cnt = 0;
// 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 (note that some devices will
// only allow to modify this parameter while NOT streaming data!) 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
const Request* pRequest = 0;
const unsigned int timeout_ms = 500;
int requestNr = INVALID_ID;
// 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 ) )
{
pRequest = fi.getRequest( requestNr );
if( pRequest->isOK() )
{
++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()
<< ", " << pRequest->requestResult.readS() << endl;
}
// raw (this might not always display a correct image but is fast and for certain applications the raw data will be the data to process
pThreadParameter->dispRaw.GetImageDisplay().SetImage( pRequest->imageData.read(), pRequest->imageWidth.read(), pRequest->imageHeight.read(), pRequest->imagePixelPitch.read() * 8, pRequest->imageLinePitch.read() );
pThreadParameter->dispRaw.GetImageDisplay().Update();
// converted. This might be slower as conversions might be needed but will display a correct image (that is not necessarily the data
// transferred from the device) e.g. 12 bit mono data can't be displayed directly
pThreadParameter->dispConverted.GetImageDisplay().SetImage( pRequest );
pThreadParameter->dispConverted.GetImageDisplay().Update();
}
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
//{
// Please note that slow systems or interface technologies in combination with high resolution sensors
// might need more time to transmit an image than the timeout value which has been passed to imageRequestWaitFor().
// If this is the case simply wait multiple times OR increase the timeout(not recommended as usually not necessary
// and potentially makes the capture thread less responsive) and rebuild this application.
// Once the device is configured for triggered image acquisition and the timeout elapsed before
// the device has been triggered this might happen as well.
// The return code would be -2119(DEV_WAIT_FOR_REQUEST_FAILED) in that case, the documentation will provide
// additional information under TDMR_ERROR in the interface reference.
// If waiting with an infinite timeout(-1) it will be necessary to call 'imageRequestReset' from another thread
// to force 'imageRequestWaitFor' to return when no data is coming from the device/can be captured.
// cout << "imageRequestWaitFor failed (" << requestNr << ", " << ImpactAcquireException::getErrorCodeAsString( requestNr ) << ")"
// << ", timeout value too small?" << endl;
//}
}
manuallyStopAcquisitionIfNeeded( pThreadParameter->pDev, fi );
// stop the displays from showing freed memory
pThreadParameter->dispRaw.GetImageDisplay().RemoveImage();
pThreadParameter->dispConverted.GetImageDisplay().RemoveImage();
// 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;
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr );
if( !pDev )
{
cout << "Unable to continue! Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
cout << "Initialising the device. This might take some time..." << endl;
try
{
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;
}
cout << "Please note that only the window displaying the converted image will display correct" << endl
<< "images all the time. The other window will simply blit the raw image data in the client" << endl
<< "area. This is faster but e.g. for 12 bit mono data or YUV data will result in unexpected" << endl
<< "results. For planar formats e.g. just the first plane might be visible." << endl
<< "For certain other formats the unconverted window might even blit no data at all." << endl
<< "This e.g. will be the case for 10-16 bit RGB packed data." << endl;
ImageDestination id( pDev );
unsigned int pixelFormats = id.pixelFormat.dictSize();
// display all available pixel formats and there numerical representation.
cout << "The following formats are available:" << endl;
for( unsigned int i = 0; i < pixelFormats; i++ )
{
cout << "[" << id.pixelFormat.getTranslationDictValue( i ) << "]: " << id.pixelFormat.getTranslationDictString( i ) << endl;
}
for( unsigned int j = 0; j < pixelFormats; j++ )
{
s_boTerminated = false;
id.pixelFormat.write( id.pixelFormat.getTranslationDictValue( j ) );
// initialise display windows
// IMPORTANT: It's NOT safe to create multiple display windows in multiple threads!!!
const string windowTitle( "Device " + pDev->serial.read() + "(pixel format " + id.pixelFormat.getTranslationDictString( j ) + ")" );
cout << "Currently using " << id.pixelFormat.getTranslationDictString( j ) << ". Press [ENTER] to switch to the next format" << endl;
unsigned int dwThreadID;
ThreadParameter threadParam( pDev, windowTitle );
// start the execution of the 'live' thread.
HANDLE hThread = ( HANDLE )_beginthreadex( 0, 0, liveThread, ( LPVOID )( &threadParam ), 0, &dwThreadID );
cin.get();
s_boTerminated = true;
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
}
cout << "Press [ENTER] to end the application" << endl;
cin.get();
return 0;
}
Grants access to devices that can be operated by this software interface.
Definition mvIMPACT_acquire.h:7171
This class and its functions represent an actual device detected by this interface in the current sys...
Definition mvIMPACT_acquire.h:6118
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6551
void open(void)
Opens a device.
Definition mvIMPACT_acquire.h:6420
ZYX read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:4300
The function interface to devices supported by this interface.
Definition mvIMPACT_acquire.h:10758
Properties to define the format of resulting images.
Definition mvIMPACT_acquire.h:12376
A base class for exceptions generated by Impact Acquire.
Definition mvIMPACT_acquire.h:256
std::string getErrorCodeAsString(void) const
Returns a string representation of the error associated with the exception.
Definition mvIMPACT_acquire.h:288
void * read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:5176
std::string read(int index=0) const
Reads a value from a property.
Definition mvIMPACT_acquire.h:5323
std::string readS(int index=0, const std::string &format="") const
Reads data from this property as a string.
Definition mvIMPACT_acquire.h:3340
Contains information about a captured buffer.
Definition mvIMPACT_acquire.h:8640
PropertyI imagePixelPitch
An integer property (read-only) containing the offset (in bytes) to the next pixel of the specified c...
Definition mvIMPACT_acquire.h:10225
PropertyI imageHeight
An integer property (read-only) containing the height of the image in pixels.
Definition mvIMPACT_acquire.h:10331
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition mvIMPACT_acquire.h:9474
PropertyIRequestResult requestResult
An enumerated integer property (read-only) defining the result of this request.
Definition mvIMPACT_acquire.h:9780
PropertyI imageWidth
An integer property (read-only) containing the width of the image in pixels.
Definition mvIMPACT_acquire.h:10320
PropertyPtr imageData
A pointer property (read-only) containing the start address of the image data.
Definition mvIMPACT_acquire.h:10187
PropertyI imageLinePitch
An integer property (read-only) containing the offset (in bytes) to the next line of each channel bel...
Definition mvIMPACT_acquire.h:10262
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14509
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:606
TDMR_ERROR
Errors reported by the device manager.
Definition mvDriverBaseEnums.h:2601
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:34