Impact Acquire SDK C++
Multi-Part Format

Since version 2.20 Impact Acquire also supports the so called multi-part format that was developed mainly within GigE Vision and GenICam working groups. This format was triggered by the need to support 3D cameras and have an interoperable way to transfer 3D data which typically consists of several independent parts of data belonging together. So the main idea was to be able to report a single block of memory to the user that contains all this information and to have an interface that can access each part of this block of memory. A typical example where the multi-part format could be used is with a 3D camera or a dual head stereo camera where either multiple images that logically belong together (left sensor and right sensor or 3D image and confidence mask). But there are other use cases as well like e.g. when a device supports a hardware JPEG encoder an application might want to access both the raw data and the compressed data for different purposes like perform image processing on the raw data while streaming the compressed data via the network.

The API for accessing GenDC or multi-part data belonging to a mvIMPACT::acquire::Request object basically consists of 2 functions:

properties residing in a separate list BufferParts within each request.

When multi-part data is reported all the properties residing in the Image list of a request are don't care thus have the cfInvisible flag set. If normal (thus non-multi-part) data is reported all properties residing in the BufferParts list of a request are don't care thus have the cfInvisible flag set.

The memory layout of a multi-part buffer can roughly be described like this:

One way of dealing with multi-part data in Impact Acquire could be implemented like this:

// ... more code
int requestNr = fi.imageRequestWaitFor( timeout_ms );
pRequest = fi.isRequestNrValid( requestNr ) ? fi.getRequest( requestNr ) : 0;
if( pRequest )
{
if( pRequest->isOK() )
{
const unsigned int bufferPartCount = pRequest->getBufferPartCount();
if( bufferPartCount > 0 )
{
// data has been delivered in multi-part format. Features like 'pRequest->imageWidth' are "don't care"
for( unsigned int i = 0; i < bufferPartCount; i++ )
{
BufferPart& part( pRequest->getBufferPart( i ) );
cout << "Part " << i << " carries data type " << part.dataType.readS() << ", " << part.dataSize.read()
<< " bytes starting at " << part.address.read() << endl;
}
}
else
{
// access feature the standard way. This buffer does not carry multi-part information
cout << "Data has been captured: "
<< pRequest->imageOffsetX.read() << "x" << pRequest->imageOffsetY.read()
<< "@"
<< pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read()
<< "(" << pRequest->imagePixelFormat.readS() << ")" << endl;
}
// chunk data evaluation would start here as it works exactly the same way no matter in which
// format the data is delivered!
// ... even more code

Limitations

Image Processing

Because of how Impact Acquire's internal image processing is currently implemented only the first part 2D buffer part encountered in a multi-part buffer can be processed by the host based Image Processing pipeline. All other buffer parts will be passed to the application as is. After at least one part has been processed and during this operation a new block of memory was allocated for the results the memory layout changes as it can be seen in the following diagram:

User Supplied Buffers

Because of how Impact Acquire's internal image processing is currently implemented providing an application allocated buffer (see mvIMPACT::acquire::FunctionInterface::imageRequestConfigure() mvIMPACT.acquire.FunctionInterface.imageRequestConfigure() for details) it is currently not possible to capture multi-part data into a user supplied buffer when at least one of the internal image processing functions that needs a destination buffer that is different from the source buffer is active. To find out whether a filter requires additional memory or not please refer to the corresponding Memory Consumption sections in the Image Processing chapter of this manual.

The reason for this limitation is that internally when a user supplied buffer is attached to a request this buffer will be attached at the output of the last filter in the internal processing chain that is active and requires a new buffer for the output data. So the user supplied buffer will serve as the 'Processed Buffer' from the last diagram in the previous section. All other parts belonging to an acquisition result will therefore NOT end up in the user supplied block of memory.