Impact Acquire SDK C++
SequenceCapture.cpp

The SequenceCapture program is a simple example, which shows, how to acquire a sequence of images with a fixed length into the main memory. The user will be prompted to enter the number of images to buffer before the acquisition starts. Afterwards always the last bufferCount images will be kept in the process memory. After the user stop the live acquisition these buffered sequence can be replayed multiple times and before the program terminates the sequence can be written into an AVI file using on of the installed compression handlers (Windows only).

Note
This example will be available on Windows® only.
Program location
The source file SequenceCapture.cpp can be found under:
%INSTALLDIR%\apps\SequenceCapture\
Note
If you have installed the package without example applications, the source code as well as the executable will not be available. On Windows® the sample application can be installed or removed from the target system at any time by simply restarting the installation package.
SequenceCapture example:
  1. Opens a Balluff device.
  2. You can set the buffer size and image format.
  3. Snaps images
Console Output
[0]: GX001559 (mvBlueCOUGAR-X122G, Family: mvBlueCOUGAR, interface layout: DeviceSpecific)
[1]: BF000306 (mvBlueFOX-202C, Family: mvBlueFOX, interface layout: DeviceSpecific)

Please enter the number in front of the listed device followed by [ENTER] to open it: 0
Using device number 0.
Enter the length of the sequence to buffer (please note that this might be limited by your systems memory): 2
Available destination formats:
[Auto]: 0
[Raw]: 1
[Mono8]: 2
[Mono10]: 6
[Mono12]: 7
[Mono12Packed_V1]: 28
[Mono12Packed_V2]: 19
[Mono14]: 8
[Mono16]: 9
[BGR888Packed]: 22
[BGR101010Packed_V2]: 23
[RGB888Packed]: 10
[RGB101010Packed]: 14
[RGB121212Packed]: 15
[RGB141414Packed]: 16
[RGB161616Packed]: 17
[RGBx888Packed]: 3
[RGB888Planar]: 30
[RGBx888Planar]: 5
[YUV422Packed]: 4
[YUV422_UYVYPacked]: 18
[YUV422_10Packed]: 20
[YUV422_UYVY_10Packed]: 21
[YUV444_UYVPacked]: 24
[YUV444_UYV_10Packed]: 25
[YUV444Packed]: 26
[YUV444_10Packed]: 27
[YUV422Planar]: 13


If AVI files shall be written please note, that most AVI compression handlers
accept RGB888Packed formats only. Apart from that planar formats are not supported
by this sample at all and YUV and Mono10-Mono16 images will not be displayed properly in
order to keep things simple.

Destination format (as integer): 3
Using RGBx888Packed.
Press [ENTER] to stop the acquisition thread
Initialising the device. This might take some time...
Info from GX001559: FramesPerSecond: 22.679305, ErrorCount: 0, CaptureTime_s: 0.392680
Info from GX001559: FramesPerSecond: 22.679299, ErrorCount: 0, CaptureTime_s: 0.392684
How it works

Using the mvIMPACT::acquire::helper::RequestProvider the program will capture images and stores the last bufferCount images in a queue. The size of this queue must be set by the user at the beginning of the program.

But now step by step through the source:

First of all a device handle must be obtained. In this sample the user is prompted to select the device he wants to use. The following function will display a list of every recognized device an will ask the user to select one of them:

DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr );

The function getDeviceFromUserInput() is included via

#include <apps/Common/exampleHelper.h>

Afterwards the user can set the length of the sequence that shall be buffered in main memory:

ImageQueue::size_type maxQueueSize = {0};
cout << "Enter the length of the sequence to buffer (please note that this might be limited by your systems memory): ";
cin >> maxQueueSize;
// display available destination formats
ImageDestination id( pDev );
vector<pair<string, TImageDestinationPixelFormat> > vAvailableDestinationFormats;
id.pixelFormat.getTranslationDict( vAvailableDestinationFormats );
cout << "Available destination formats: " << endl;
for( const auto& format : vAvailableDestinationFormats )
{
cout << "[" << format.first << "]: " << format.second << endl;
}
cout << endl << endl;
cout << "If AVI files shall be written please note, that most AVI compression handlers" << endl
<< "accept RGB888Packed formats only. Apart from that planar formats are not supported" << endl
<< "by this sample in order to keep things simple." << endl << endl
<< "Destination format (as integer): ";
int destinationPixelFormat = {0};
cin >> destinationPixelFormat;
// set destination format
try
{
id.pixelFormat.write( static_cast<TImageDestinationPixelFormat>( destinationPixelFormat ) );
}
catch( const ImpactAcquireException& e )
{
cout << "Failed to set destination pixel format(" << e.getErrorCodeAsString() << "), using default" << endl;
id.pixelFormat.write( idpfRGB888Packed );
}
cout << "Using " << id.pixelFormat.readS() << "." << endl;
TImageDestinationPixelFormat
Defines the pixel format of the result image.
Definition mvDriverBaseEnums.h:3205

Now the display window is initialized and the acquisition is started. From now on the application will constantly display a live image until the user stops the acquisition

string windowTitle( "mvIMPACT_acquire sample, Device " + pDev->serial.read() ); helper::RequestProvider requestProvider( pDev );
// initialise display window
// IMPORTANT: It's NOT save to create multiple display windows in multiple threads!!!
// IMPORTANT: If you need to access the queue from multiple threads appropriate security
// mechanisms (e.g. critical sections) must be used. Here we don't care about that as we
// will NOT access the queue from multiple threads at the same time!
ThreadParameter threadParam( pDev, imageQueue, maxQueueSize, captureFrameRate );
requestProvider.acquisitionStart( myThreadCallback, std::ref( threadParam ) );
if( _getch() == EOF )
{
cout << "Calling '_getch()' did return EOF...\n";
}
const double fr = threadParam.getStatistics().framesPerSecond.read();
threadParam.setFrameRate( static_cast<int>( fr ) );
if( ( fr - static_cast<double>( static_cast<int>( fr ) ) ) >= 0.5 )
{
threadParam.setFrameRate( threadParam.getFrameRate() + 1 );
}
requestProvider.acquisitionStop();

During the thread execution the images will be stored in the queue until the user defined queue size is reached. Then each time a new images is added the queue the oldest one will be removed:

// append a new image at the end of the queue (the image will be deep-copied)
threadParameter.getImageQueue().push_back( pRequest->getImageBufferDesc().clone() );
// if the queue has the user defined max. number of entries remove the oldest one
// with this method we always keep the most recent images
if( threadParameter.getImageQueue().size() > threadParameter.getMaxQueueSize() )
{
threadParameter.getImageQueue().pop_front();
}

The user can stop the acquisition by pressing any key. Afterwards he can replay the captured sequence as many times as he wants by pressing "y". From now on the actual hardware device is no longer needed. To stop replaying the captured images the user can press any other key:

cout << "Press 'y' to replay the captured sequence of " << qSize << " images from memory or any other key to end the replay loop." << endl;
char c = static_cast<char>( _getch() );
if( c != 'y' )
{
boRun = false;
continue;
}
// delay between two image during display
const DWORD frameDelay = ( threadParam.getFrameRate() > 0 ) ? 1000 / threadParam.getFrameRate() : 40;
// obtain pointer to display structure
ImageDisplay& display = threadParam.getDisplayWindow().GetImageDisplay();
cout << "Replaying the last " << qSize << " captured images with " << 1000 / frameDelay << " Hz..." << endl;
for( const auto& imageBufferDescriptor : imageQueue )
{
display.SetImage( imageBufferDescriptor.getBuffer() );
display.Update();
this_thread::sleep_for( chrono::milliseconds( frameDelay ) );
}

Now the sequence can be saved as an AVI file before ending the application by pressing "y":

// ask the user if the sequence shall be written into a AVI file
cout << endl;
cout << "If you want to save the captured sequence press 'y' or any other key to end the application: ";
if( _getch() != 'y' )
{
return 0;
}
cout << endl << "Please enter the file name for the resulting AVI stream(use proper file extensions like *.avi as otherwise creating the stream may fail): ";
string fileName;
cin >> fileName;
// Now we have to create and configure the AVI stream
unique_ptr<AVIWrapper> pAVIWrapper;
boRun = true;
while( boRun )
{
try
{
// create the AVI file builder
pAVIWrapper = unique_ptr<AVIWrapper>( new AVIWrapper() );
pAVIWrapper->OpenAVIFile( fileName.c_str(), OF_WRITE | OF_CREATE | OF_SHARE_DENY_WRITE );
// To select from installed compression handlers, pass codecMax as codec to the next function, which is also
// the default parameter if not specified. Windows will display a dialog to select the codec then.
// Most codecs only accept RGB888 data with no alpha byte. Make sure that either the driver is
// operated in RGB888Packed mode or you supply the correct image data converted by hand here.
cout << "Please select a compression handler from the dialog box" << endl << endl;
const ImageBuffer* pIB = imageQueue.front().getBuffer();
pAVIWrapper->CreateAVIStreamFromDIBs( pIB->iWidth, pIB->iHeight, pIB->iBytesPerPixel * 8, threadParam.getFrameRate(), 8000, "myStream" );
boRun = false;
}
catch( const AVIException& e )
{
cout << "Error while creating AVI stream(" << string( e.what() ) << ")." << endl
<< "Please note, that not every codec will accept every pixel format, thus this error might" << endl
<< "appear without changing the destination pixel format within the driver. However the" << endl
<< "format selected in this sample (RGB888Packed) works for the greatest number of codecs" << endl
<< "Unable to continue. Press 'q' to end the application or any other key to select a different" << endl
<< "compression handler." << endl;
if( _getch() == 'q' )
{
return 1;
}
}
}
// we should have a valid AVI stream by now thus we can start to write the images to it
for( ImageQueue::size_type x = 0; x < qSize; x++ )
{
cout << "Storing image " << x << " in stream " << fileName << ".\r";
const ImageBuffer* pIB = imageQueue[x].getBuffer();
// Unfortunately we have to flip the images as they are stored upside down in the stream...
inplaceHorizontalMirror( pIB );
pAVIWrapper->SaveDataToAVIStream( reinterpret_cast<unsigned char*>( pIB->vpData ), pIB->iSize );
}
return 0;
Source code
//
// @description: Example applications for Impact Acquire
// @copyright: Copyright (C) 2005 - 2023 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.
//
#include <conio.h>
#include <deque>
#include <iostream>
#include <apps/Common/aviwrapper.h>
#include <apps/Common/exampleHelper.h>
#include <mvDisplay/Include/mvIMPACT_acquire_display.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_helper.h>
using namespace std;
using namespace mvIMPACT::acquire;
using ImageQueue = deque<ImageBufferDesc>;
//-----------------------------------------------------------------------------
class ThreadParameter
//-----------------------------------------------------------------------------
{
Device* pDev_;
unsigned int requestsCaptured_;
Statistics statistics_;
ImageDisplayWindow displayWindow_;
ImageQueue& imageQueue_;
ImageQueue::size_type maxQueueSize_;
int frameRate_;
public:
explicit ThreadParameter( Device* p, ImageQueue& q, ImageQueue::size_type maxSize, int fr )
: pDev_( p ), requestsCaptured_( 0 ), statistics_( p ), displayWindow_( "mvIMPACT_acquire sample, Device " + p->serial.read() ), imageQueue_( q ), maxQueueSize_( maxSize ), frameRate_( fr ) {}
ThreadParameter( const ThreadParameter& src ) = delete;
ThreadParameter& operator=( const ThreadParameter& rhs ) = delete;
void incRequestsCaptured( void )
{
++requestsCaptured_;
}
unsigned int getRequestsCaptured( void ) const
{
return requestsCaptured_;
}
const Statistics& getStatistics( void ) const
{
return statistics_;
}
int getFrameRate( void ) const
{
return frameRate_;
}
void setFrameRate( int fr )
{
frameRate_ = fr;
}
Device* getDevice( void ) const
{
return pDev_;
}
ImageDisplayWindow& getDisplayWindow( void )
{
return displayWindow_;
}
ImageQueue& getImageQueue( void ) const
{
return imageQueue_;
}
ImageQueue::size_type getMaxQueueSize( void ) const
{
return maxQueueSize_;
}
};
//-----------------------------------------------------------------------------
void inplaceHorizontalMirror( const ImageBuffer* p )
//-----------------------------------------------------------------------------
{
int upperHalfOfLines = p->iHeight / 2; // the line in the middle (if existent) doesn't need to be processed!
size_t pitch = p->pChannels[0].iLinePitch; // this only works for image formats where each channel has the same line pitch!
char* pLowerLine = static_cast<char*>( p->vpData ) + ( ( p->iHeight - 1 ) * pitch );
char* pUpperLine = static_cast<char*>( p->vpData );
unique_ptr<char[]> pTmpLine( new char[pitch] );
for( int y = 0; y < upperHalfOfLines; y++ )
{
memcpy( pTmpLine.get(), pUpperLine, pitch );
memcpy( pUpperLine, pLowerLine, pitch );
memcpy( pLowerLine, pTmpLine.get(), pitch );
pUpperLine += pitch;
pLowerLine -= pitch;
}
}
//-----------------------------------------------------------------------------
// Currently only the mvBlueFOX supports HRTC and thus the definition of an
// absolute frame rate during the capture process.
void setupBlueFOXFrameRate( Device* pDev, int& frameRate_Hz )
//-----------------------------------------------------------------------------
{
cout << "To use the HRTC to configure the mvBlueFOX to capture with a defined frequency press 'y'." << endl;
if( _getch() != 'y' )
{
return;
}
// mvBlueFOX devices can define a fixed frame frequency
cout << "Enter the desired capture frame rate in Hz: ";
cin >> frameRate_Hz;
cout << "Trying to capture at " << frameRate_Hz << " frames per second. Please make sure the device can deliver this frame rate" << endl
<< "as otherwise the resulting AVI stream will be replayed with an incorrect speed" << endl;
int frametime_us = static_cast<int>( 1000000.0 * ( 1.0 / static_cast<double>( frameRate_Hz ) ) );
const int TRIGGER_PULSE_WIDTH_us = {100};
if( frametime_us < 2 * TRIGGER_PULSE_WIDTH_us )
{
cout << "frame rate too high (" << frameRate_Hz << "). Using 10 Hz." << endl;
frametime_us = 100000;
}
CameraSettingsBlueFOX bfs( pDev );
if( bfs.expose_us.read() > frametime_us / 2 )
{
ostringstream oss;
oss << "Reducing frame-time from " << bfs.expose_us.read() << " us to " << frametime_us / 2 << " us." << endl
<< "Higher values are possible but require a more sophisticated HRTC program" << endl;
bfs.expose_us.write( frametime_us / 2 );
}
IOSubSystemBlueFOX bfIOs( pDev );
// define a HRTC program that results in a define image frequency
// the hardware real time controller shall be used to trigger an image
bfs.triggerSource.write( ctsRTCtrl );
// when the hardware real time controller switches the trigger signal to
// high the exposure of the image shall start
bfs.triggerMode.write( ctmOnRisingEdge );
// error checks
if( bfIOs.RTCtrProgramCount() == 0 )
{
// no HRTC controllers available (this never happens for the mvBlueFOX)
cout << "This device (" << pDev->product.read() << ") doesn't support HRTC" << endl;
return;
}
RTCtrProgram* pRTCtrlprogram = bfIOs.getRTCtrProgram( 0 );
if( !pRTCtrlprogram )
{
// this only should happen if the system is short of memory
cout << "Error! No valid program. Short of memory?" << endl;
return;
}
// start of the program
// we need 5 steps for the program
pRTCtrlprogram->setProgramSize( 5 );
// wait a certain amount of time to achieve the desired frequency
int progStep = {0};
RTCtrProgramStep* pRTCtrlStep = pRTCtrlprogram->programStep( progStep++ );
pRTCtrlStep->opCode.write( rtctrlProgWaitClocks );
pRTCtrlStep->clocks_us.write( frametime_us - TRIGGER_PULSE_WIDTH_us );
// trigger an image
pRTCtrlStep = pRTCtrlprogram->programStep( progStep++ );
pRTCtrlStep->opCode.write( rtctrlProgTriggerSet );
// high time for the trigger signal (should not be smaller than 100 us)
pRTCtrlStep = pRTCtrlprogram->programStep( progStep++ );
pRTCtrlStep->opCode.write( rtctrlProgWaitClocks );
pRTCtrlStep->clocks_us.write( TRIGGER_PULSE_WIDTH_us );
// end trigger signal
pRTCtrlStep = pRTCtrlprogram->programStep( progStep++ );
pRTCtrlStep->opCode.write( rtctrlProgTriggerReset );
// restart the program
pRTCtrlStep = pRTCtrlprogram->programStep( progStep++ );
pRTCtrlStep->opCode.write( rtctrlProgJumpLoc );
pRTCtrlStep->address.write( 0 );
// start the program
pRTCtrlprogram->mode.write( rtctrlModeRun );
// Now this camera will deliver images at exactly the desired frequency
// when it is constantly feed with image requests and the camera can deliver
// images at this frequency.
}
//-----------------------------------------------------------------------------
void myThreadCallback( shared_ptr<Request> pRequest, ThreadParameter& threadParameter )
//-----------------------------------------------------------------------------
{
threadParameter.incRequestsCaptured();
// display some statistical information every 100th image
if( threadParameter.getRequestsCaptured() % 100 == 0 )
{
const Statistics& s = threadParameter.getStatistics();
cout << "Info from " << threadParameter.getDevice()->serial.read()
<< ": " << s.framesPerSecond.name() << ": " << s.framesPerSecond.readS()
<< ", " << s.errorCount.name() << ": " << s.errorCount.readS()
<< ", " << s.captureTime_s.name() << ": " << s.captureTime_s.readS() << endl;
}
if( pRequest->isOK() )
{
threadParameter.getDisplayWindow().GetImageDisplay().SetImage( pRequest );
threadParameter.getDisplayWindow().GetImageDisplay().Update();
// append a new image at the end of the queue (the image will be deep-copied)
threadParameter.getImageQueue().push_back( pRequest->getImageBufferDesc().clone() );
// if the queue has the user defined max. number of entries remove the oldest one
// with this method we always keep the most recent images
if( threadParameter.getImageQueue().size() > threadParameter.getMaxQueueSize() )
{
threadParameter.getImageQueue().pop_front();
}
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
Device* pDev = getDeviceFromUserInput( devMgr );
if( pDev == nullptr )
{
cout << "Could not obtain a valid pointer to a device. Unable to continue! Press any key to end the program." << endl;
return _getch();
}
cout << "Initialising the device. This might take some time..." << endl
<< endl
<< "PLEASE NOTE THAT THIS EXAMPLE APPLICATION MAKES USE OF A VERY OLD, OUTDATED WINDOWS ONLY API WHICH IS NOT RECOMMENDED FOR NEW PROJECTS!" << endl
<< "There are various other, more portable ways to encode/store a video stream there day. Please consider using the FFmpeg library (see" << endl
<< "'ContinuousCaptureFFmpeg' in the C++ manual) or something similar instead!" << 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 the device " << pDev->serial.read()
<< "(error code: " << e.getErrorCodeAsString() << ").";
return 1;
}
int captureFrameRate = {0};
if( pDev->family.read() == "mvBlueFOX" )
{
setupBlueFOXFrameRate( pDev, captureFrameRate );
}
ImageQueue::size_type maxQueueSize = {0};
cout << "Enter the length of the sequence to buffer (please note that this might be limited by your systems memory): ";
cin >> maxQueueSize;
// display available destination formats
ImageDestination id( pDev );
vector<pair<string, TImageDestinationPixelFormat> > vAvailableDestinationFormats;
id.pixelFormat.getTranslationDict( vAvailableDestinationFormats );
cout << "Available destination formats: " << endl;
for( const auto& format : vAvailableDestinationFormats )
{
cout << "[" << format.first << "]: " << format.second << endl;
}
cout << endl << endl;
cout << "If AVI files shall be written please note, that most AVI compression handlers" << endl
<< "accept RGB888Packed formats only. Apart from that planar formats are not supported" << endl
<< "by this sample in order to keep things simple." << endl << endl
<< "Destination format (as integer): ";
int destinationPixelFormat = {0};
cin >> destinationPixelFormat;
// set destination format
try
{
id.pixelFormat.write( static_cast<TImageDestinationPixelFormat>( destinationPixelFormat ) );
}
catch( const ImpactAcquireException& e )
{
cout << "Failed to set destination pixel format(" << e.getErrorCodeAsString() << "), using default" << endl;
id.pixelFormat.write( idpfRGB888Packed );
}
cout << "Using " << id.pixelFormat.readS() << "." << endl;
// start the execution of the 'live' thread.
cout << "Press [ENTER] to stop the acquisition thread" << endl;
ImageQueue imageQueue;
helper::RequestProvider requestProvider( pDev );
// initialise display window
// IMPORTANT: It's NOT safe to create multiple display windows in multiple threads!!!
// IMPORTANT: If you need to access the queue from multiple threads appropriate security
// mechanisms (e.g. critical sections) must be used. Here we don't care about that as we
// will NOT access the queue from multiple threads at the same time!
ThreadParameter threadParam( pDev, imageQueue, maxQueueSize, captureFrameRate );
requestProvider.acquisitionStart( myThreadCallback, std::ref( threadParam ) );
if( _getch() == EOF )
{
cout << "Calling '_getch()' did return EOF...\n";
}
const double fr = threadParam.getStatistics().framesPerSecond.read();
threadParam.setFrameRate( static_cast<int>( fr ) );
if( ( fr - static_cast<double>( static_cast<int>( fr ) ) ) >= 0.5 )
{
threadParam.setFrameRate( threadParam.getFrameRate() + 1 );
}
requestProvider.acquisitionStop();
if( imageQueue.empty() )
{
cout << "No images have been captured thus no playback or storage can be performed"
<< "Press any key to end the application" << endl;
if( _getch() == EOF )
{
cout << "Calling '_getch()' did return EOF...\n";
}
return 1;
}
const ImageQueue::size_type qSize = imageQueue.size();
bool boRun = true;
while( boRun )
{
cout << "Press 'y' to replay the captured sequence of " << qSize << " images from memory or any other key to end the replay loop." << endl;
char c = static_cast<char>( _getch() );
if( c != 'y' )
{
boRun = false;
continue;
}
// delay between two image during display
const DWORD frameDelay = ( threadParam.getFrameRate() > 0 ) ? 1000 / threadParam.getFrameRate() : 40;
// obtain pointer to display structure
ImageDisplay& display = threadParam.getDisplayWindow().GetImageDisplay();
cout << "Replaying the last " << qSize << " captured images with " << 1000 / frameDelay << " Hz..." << endl;
for( const auto& imageBufferDescriptor : imageQueue )
{
display.SetImage( imageBufferDescriptor.getBuffer() );
display.Update();
this_thread::sleep_for( chrono::milliseconds( frameDelay ) );
}
}
// ask the user if the sequence shall be written into a AVI file
cout << endl;
cout << "If you want to save the captured sequence press 'y' or any other key to end the application: ";
if( _getch() != 'y' )
{
return 0;
}
cout << endl << "Please enter the file name for the resulting AVI stream(use proper file extensions like *.avi as otherwise creating the stream may fail): ";
string fileName;
cin >> fileName;
// Now we have to create and configure the AVI stream
unique_ptr<AVIWrapper> pAVIWrapper;
boRun = true;
while( boRun )
{
try
{
// create the AVI file builder
pAVIWrapper = unique_ptr<AVIWrapper>( new AVIWrapper() );
pAVIWrapper->OpenAVIFile( fileName.c_str(), OF_WRITE | OF_CREATE | OF_SHARE_DENY_WRITE );
// To select from installed compression handlers, pass codecMax as codec to the next function, which is also
// the default parameter if not specified. Windows will display a dialog to select the codec then.
// Most codecs only accept RGB888 data with no alpha byte. Make sure that either the driver is
// operated in RGB888Packed mode or you supply the correct image data converted by hand here.
cout << "Please select a compression handler from the dialog box (which might be hidden behind this window)" << endl << endl;
const ImageBuffer* pIB = imageQueue.front().getBuffer();
pAVIWrapper->CreateAVIStreamFromDIBs( pIB->iWidth, pIB->iHeight, pIB->iBytesPerPixel * 8, threadParam.getFrameRate(), 8000, "myStream" );
boRun = false;
}
catch( const AVIException& e )
{
cout << "Error while creating AVI stream(" << string( e.what() ) << ")." << endl
<< "Please note, that not every codec will accept every pixel format, thus this error might" << endl
<< "appear without changing the destination pixel format within the driver. However the" << endl
<< "format selected in this sample (RGB888Packed) works for the greatest number of codecs" << endl
<< "Unable to continue. Press 'q' to end the application or any other key to select a different" << endl
<< "compression handler." << endl;
if( _getch() == 'q' )
{
return 1;
}
}
}
// we should have a valid AVI stream by now thus we can start to write the images to it
for( ImageQueue::size_type x = 0; x < qSize; x++ )
{
cout << "Storing image " << x << " in stream " << fileName << ".\r";
const ImageBuffer* pIB = imageQueue[x].getBuffer();
// Unfortunately we have to flip the images as they are stored upside down in the stream...
inplaceHorizontalMirror( pIB );
pAVIWrapper->SaveDataToAVIStream( reinterpret_cast<unsigned char*>( pIB->vpData ), pIB->iSize );
}
return 0;
}
mvBlueFOX related camera settings(Device specific interface layout only).
Definition mvIMPACT_acquire.h:20010
std::string name(void) const
Returns the name of the component referenced by this object.
Definition mvIMPACT_acquire.h:1206
Grants access to devices that can be operated by this software interface.
Definition mvIMPACT_acquire.h:7159
This class and its functions represent an actual device detected by this interface in the current sys...
Definition mvIMPACT_acquire.h:6118
PropertyS product
A string property (read-only) containing the product name of this device.
Definition mvIMPACT_acquire.h:6536
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6550
void open(void)
Opens a device.
Definition mvIMPACT_acquire.h:6419
PropertyS family
A string property (read-only) containing the family name of this device.
Definition mvIMPACT_acquire.h:6525
const EnumPropertyI & write(ZYX value, int index=0) const
Writes one value to the property.
Definition mvIMPACT_acquire.h:4426
A class to handle the digital inputs and outputs for mvBlueFOX USB cameras(Device specific interface ...
Definition mvIMPACT_acquire.h:16765
Properties to define the format of resulting images.
Definition mvIMPACT_acquire.h:12364
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
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
A class to represent one step of a real time control(RTCtr) program (Device specific interface layout...
Definition mvIMPACT_acquire.h:15659
PropertyI address
An integer property, which defines the absolute jump address within this mvIMPACT::acquire::RTCtrProg...
Definition mvIMPACT_acquire.h:15684
PropertyIRTProgOpCodes opCode
An enumerated integer property defining the general purpose of this mvIMPACT::acquire::RTCtrProgramSt...
Definition mvIMPACT_acquire.h:15721
PropertyI clocks_us
An integer property, which defines the waiting time mvIMPACT::acquire::RTCtrProgram.
Definition mvIMPACT_acquire.h:15694
A class to represent real time control programs(Device specific interface layout only).
Definition mvIMPACT_acquire.h:16004
PropertyIRTCtrlModes mode
An enumerated integer property defining the current state this program is into.
Definition mvIMPACT_acquire.h:16165
RTCtrProgramStep * programStep(unsigned int nr) const
Returns a pointer to a program instruction of the program.
Definition mvIMPACT_acquire.h:16147
void setProgramSize(int newSize)
A function to define the number of instructions this program should consist of.
Definition mvIMPACT_acquire.h:16123
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14497
PropertyF framesPerSecond
A float property (read-only) containing the current number of frames captured per second.
Definition mvIMPACT_acquire.h:14564
PropertyF captureTime_s
A float property (read-only) containing the overall time an image request spent in the device drivers...
Definition mvIMPACT_acquire.h:14548
PropertyI errorCount
An integer property (read-only) containing the overall count of image requests which returned with an...
Definition mvIMPACT_acquire.h:14556
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:587
A class that can be used for displaying images within existing windows or GUI elements that can provi...
Definition mvIMPACT_acquire_display.h:176
void SetImage(const void *pData, int width, int height, int bitsPerPixel, int pitch)
Sets the next image to display.
Definition mvIMPACT_acquire_display.h:296
void Update(void) const
Immediately redraws the current image.
Definition mvIMPACT_acquire_display.h:385
A helper class that can be used to implement a simple continuous acquisition from a device.
Definition mvIMPACT_acquire_helper.h:432
int iHeight
The height of the image in pixel or lines.
Definition mvImageBuffer.h:98
int iWidth
The width of the image in pixel.
Definition mvImageBuffer.h:100
int iLinePitch
The offset (in bytes) to the next line of this channel.
Definition mvImageBuffer.h:70
void * vpData
The starting address of the image.
Definition mvImageBuffer.h:157
ChannelData * pChannels
A pointer to an array of channel specific image data.
Definition mvImageBuffer.h:166
int iBytesPerPixel
The number of bytes per pixel.
Definition mvImageBuffer.h:96
int iSize
The size (in bytes) of the whole image.
Definition mvImageBuffer.h:112
Fully describes a captured image.
Definition mvImageBuffer.h:94
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