#ifdef _MSC_VER
# if _MSC_VER < 1300
# pragma warning( disable : 4786 )
# endif
#endif
#include <windows.h>
#include <process.h>
#include <conio.h>
#include <iostream>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#include <mvDisplay/Include/mvIMPACT_acquire_display.h>
#include <deque>
#include <apps/Common/exampleHelper.h>
#include <apps/Common/aviwrapper.h>
using namespace std;
static bool s_boTerminated = false;
typedef deque<ImageBufferDesc> ImageQueue;
class ThreadParameter
{
ImageQueue& imageQueue_;
ImageQueue::size_type maxQueueSize_;
int frameRate_;
ThreadParameter& operator=( const ThreadParameter& rhs );
public:
ThreadParameter(
Device* p,
const std::string& windowTitle, ImageQueue& q, ImageQueue::size_type maxSize,
int fr )
: pDev_( p ), displayWindow_( windowTitle ), imageQueue_( q ), maxQueueSize_( maxSize ), frameRate_( fr ) {}
int getFrameRate( void ) const
{
return frameRate_;
}
void setFrameRate( int fr )
{
frameRate_ = fr;
}
Device* getDevice(
void )
const
{
return pDev_;
}
{
return displayWindow_;
}
ImageQueue& getImageQueue( void ) const
{
return imageQueue_;
}
ImageQueue::size_type getMaxQueueSize( void ) const
{
return maxQueueSize_;
}
};
{
int upperHalfOfLines = p->
iHeight / 2;
char* pLowerLine =
static_cast<char*
>( p->
vpData ) + ( ( p->
iHeight - 1 ) * pitch );
char* pUpperLine =
static_cast<char*
>( p->
vpData );
char* pTmpLine = new char[pitch];
for( int y = 0; y < upperHalfOfLines; y++ )
{
memcpy( pTmpLine, pUpperLine, pitch );
memcpy( pUpperLine, pLowerLine, pitch );
memcpy( pLowerLine, pTmpLine, pitch );
pUpperLine += pitch;
pLowerLine -= pitch;
}
delete [] pTmpLine;
}
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;
}
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;
}
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 );
}
bfs.triggerSource.write( ctsRTCtrl );
bfs.triggerMode.write( ctmOnRisingEdge );
if( bfIOs.RTCtrProgramCount() == 0 )
{
cout <<
"This device (" << pDev->
product.
read() <<
") doesn't support HRTC" << endl;
return;
}
if( !pRTCtrlprogram )
{
cout << "Error! No valid program. Short of memory?" << endl;
return;
}
int progStep = 0;
pRTCtrlStep->
clocks_us.
write( frametime_us - TRIGGER_PULSE_WIDTH_us );
pRTCtrlStep = pRTCtrlprogram->
programStep( progStep++ );
pRTCtrlStep = pRTCtrlprogram->
programStep( progStep++ );
pRTCtrlStep = pRTCtrlprogram->
programStep( progStep++ );
pRTCtrlStep = pRTCtrlprogram->
programStep( progStep++ );
}
unsigned int __stdcall liveThread( void* pData )
{
ThreadParameter* pThreadParameter = reinterpret_cast<ThreadParameter*>( pData );
cout << "Initialising the device. This might take some time..." << endl;
try
{
if( !pThreadParameter->getDevice()->isOpen() )
{
pThreadParameter->getDevice()->open();
}
}
{
cout << "An error occurred while opening device " << pThreadParameter->getDevice()->serial.read()
<<
"(error code: " << e.
getErrorCodeAsString() <<
"). Press any key to end the application..." << endl;
return _getch();
}
ImageDisplay& display = pThreadParameter->getDisplayWindow().GetImageDisplay();
Statistics statistics( pThreadParameter->getDevice() );
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->getDevice(), fi );
const unsigned int timeout_ms = 500;
unsigned int cnt = 0;
while( !s_boTerminated )
{
const int requestNr = fi.imageRequestWaitFor( timeout_ms );
if( fi.isRequestNrValid( requestNr ) )
{
const Request* pRequest = fi.getRequest( requestNr );
{
++cnt;
if( cnt % 100 == 0 )
{
cout << "Info from " << pThreadParameter->getDevice()->serial.read()
<< ": " << statistics.framesPerSecond.name() << ": " << statistics.framesPerSecond.readS()
<< ", " << statistics.errorCount.name() << ": " << statistics.errorCount.readS()
<< ", " << statistics.captureTime_s.name() << ": " << statistics.captureTime_s.readS() << endl;
}
if( pThreadParameter->getImageQueue().size() > pThreadParameter->getMaxQueueSize() )
{
pThreadParameter->getImageQueue().pop_front();
}
}
else
{
}
if( fi.isRequestNrValid( lastRequestNr ) )
{
fi.imageRequestUnlock( lastRequestNr );
}
lastRequestNr = requestNr;
fi.imageRequestSingle();
}
else
{
cout << "imageRequestWaitFor failed (" << requestNr << ", " << ImpactAcquireException::getErrorCodeAsString( requestNr ) << ")"
<< ", timeout value too small?" << endl;
}
}
const double fr = statistics.framesPerSecond.read();
pThreadParameter->setFrameRate( static_cast<int>( fr ) );
if( ( fr - static_cast<double>( static_cast<int>( fr ) ) ) >= 0.5 )
{
pThreadParameter->setFrameRate( pThreadParameter->getFrameRate() + 1 );
}
manuallyStopAcquisitionIfNeeded( pThreadParameter->getDevice(), fi );
if( fi.isRequestNrValid( lastRequestNr ) )
{
fi.imageRequestUnlock( lastRequestNr );
}
fi.imageRequestReset( 0, 0 );
return 0;
}
int main( void )
{
Device* pDev = getDeviceFromUserInput( devMgr );
if( !pDev )
{
cout << "Could not obtain a valid pointer to a device. Unable to continue! Press any key to end the program." << endl;
return _getch();
}
int captureFrameRate = 0;
{
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;
vector<pair<string, TImageDestinationPixelFormat> > vAvailableDestinationFormats;
id.pixelFormat.getTranslationDict( vAvailableDestinationFormats );
int vSize = static_cast<int>( vAvailableDestinationFormats.size() );
cout << "Available destination formats: " << endl;
for( int i = 0; i < vSize; i++ )
{
cout << "[" << vAvailableDestinationFormats[i].first << "]: " << vAvailableDestinationFormats[i].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;
try
{
}
{
cout <<
"Failed to set destination pixel format(" << e.
getErrorCodeAsString() <<
"), using default" << endl;
id.pixelFormat.write( idpfRGB888Packed );
}
cout << "Using " << id.pixelFormat.readS() << "." << endl;
cout << "Press [ENTER] to stop the acquisition thread" << endl;
unsigned int dwThreadID;
ImageQueue imageQueue;
string windowTitle(
"mvIMPACT_acquire sample, Device " + pDev->
serial.
read() );
ThreadParameter threadParam( pDev, windowTitle, imageQueue, maxQueueSize, captureFrameRate );
HANDLE hThread = ( HANDLE )_beginthreadex( 0, 0, liveThread, ( LPVOID )( &threadParam ), 0, &dwThreadID );
if( _getch() == EOF )
{
cout << "Calling '_getch()' did return EOF...\n";
}
s_boTerminated = true;
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
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;
}
const DWORD frameDelay = ( threadParam.getFrameRate() > 0 ) ? 1000 / threadParam.getFrameRate() : 40;
ImageDisplay& display = threadParam.getDisplayWindow().GetImageDisplay();
cout << "Replaying the last " << qSize << " captured images with " << 1000 / frameDelay << " Hz..." << endl;
for( ImageQueue::size_type i = 0; i < qSize; i++ )
{
display.
SetImage( imageQueue[i].getBuffer() );
Sleep( frameDelay );
}
}
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;
boRun = true;
while( boRun )
{
try
{
AVIWrapper myAVIWrapper;
myAVIWrapper.OpenAVIFile( fileName.c_str(), OF_WRITE | OF_CREATE | OF_SHARE_DENY_WRITE );
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();
myAVIWrapper.CreateAVIStreamFromDIBs( pIB->
iWidth, pIB->
iHeight, pIB->
iBytesPerPixel * 8, threadParam.getFrameRate(), 8000,
"myStream" );
boRun = false;
for( ImageQueue::size_type x = 0; x < qSize; x++ )
{
cout << "Storing image " << x << " in stream " << fileName << ".\r";
inplaceHorizontalMirror( pIB );
myAVIWrapper.SaveDataToAVIStream(
reinterpret_cast<unsigned char*
>( pIB->
vpData ), pIB->
iSize );
}
}
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;
}
}
}
return 0;
}
mvBlueFOX related camera settings(Device specific interface layout only).
Definition mvIMPACT_acquire.h:20035
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 product
A string property (read-only) containing the product name of this device.
Definition mvIMPACT_acquire.h:6537
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition mvIMPACT_acquire.h:6551
PropertyS family
A string property (read-only) containing the family name of this device.
Definition mvIMPACT_acquire.h:6526
const EnumPropertyI & write(ZYX value, int index=0) const
Writes one value to the property.
Definition mvIMPACT_acquire.h:4426
The function interface to devices supported by this interface.
Definition mvIMPACT_acquire.h:10758
A class to handle the digital inputs and outputs for mvBlueFOX USB cameras(Device specific interface ...
Definition mvIMPACT_acquire.h:16787
ImageBufferDesc clone(void) const
Returns a deep copy of the mvIMPACT::acquire::ImageBuffer object referenced by this descriptor.
Definition mvIMPACT_acquire.h:8276
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
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:15681
PropertyI address
An integer property, which defines the absolute jump address within this mvIMPACT::acquire::RTCtrProg...
Definition mvIMPACT_acquire.h:15706
PropertyIRTProgOpCodes opCode
An enumerated integer property defining the general purpose of this mvIMPACT::acquire::RTCtrProgramSt...
Definition mvIMPACT_acquire.h:15743
PropertyI clocks_us
An integer property, which defines the waiting time mvIMPACT::acquire::RTCtrProgram.
Definition mvIMPACT_acquire.h:15716
A class to represent real time control programs(Device specific interface layout only).
Definition mvIMPACT_acquire.h:16026
PropertyIRTCtrlModes mode
An enumerated integer property defining the current state this program is into.
Definition mvIMPACT_acquire.h:16187
RTCtrProgramStep * programStep(unsigned int nr) const
Returns a pointer to a program instruction of the program.
Definition mvIMPACT_acquire.h:16169
void setProgramSize(int newSize)
A function to define the number of instructions this program should consist of.
Definition mvIMPACT_acquire.h:16145
Contains information about a captured buffer.
Definition mvIMPACT_acquire.h:8640
const ImageBufferDesc & getImageBufferDesc(void) const
Returns a const reference to the image buffer descriptor of this request.
Definition mvIMPACT_acquire.h:9077
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
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
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 RemoveImage(void)
Removes the current image from the display.
Definition mvIMPACT_acquire_display.h:395
void SetImage(const void *pData, int width, int height, int bitsPerPixel, int pitch)
Sets the next image to display.
Definition mvIMPACT_acquire_display.h:316
void Update(void) const
Immediately redraws the current image.
Definition mvIMPACT_acquire_display.h:405
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
TImageDestinationPixelFormat
Defines the pixel format of the result image.
Definition mvDriverBaseEnums.h:3205
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
@ DMR_NO_ERROR
The function call was executed successfully.
Definition mvDriverBaseEnums.h:2603
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