mvIMPACT Acquire SDK C++
CaptureToOpenGLMemory.cpp

The CaptureToOpenGLMemory program is a short example which shows how display the image data acquired by mvIMPACT Acquire using OpenGL.

Since
2.41.0
Note
The source code of this example makes use of the glfw and the glew project.
The following packages are needed to build the code:
Windows
Linux
Note
A C++ 11 compatible compiler is needed to build this example application! You might need to explicitly enable C++11 support in your Makefile!
CaptureToOpenGLMemory example:
  1. Opens a device
  2. Configures the device and tries to setup a OpenGL supported window.
  3. Initializes OpenGL-managed memory and attaches this memory to image requests
  4. Starts the image acquisition and displays the images using OpenGL in an OpenGL based window
How it works

For the continuous acquisition and memory allocation, this sample uses CaptureToUserMemory.cpp as a basis. So this example is recommended as a starting point before moving on here!

The example will list all available devices first. After selecting a device, the pixel formats supported by the display are listed for selection. If a device doesn't transmit the desired format the driver's internal format converter will generate the appropriate format. This consumes some time and should be avoided in a real world application if possible. After selecting a format to use, the image acquisition will start and display the output within a OpenGL supported window. To end the application the display window must be closed.

This example works like the CaptureToUserMemory.cpp example, but instead of allocating heap memory, a OpenGL pixel buffer object is created. To improve the image display times significantly, the image pixel data needs to be stored in a format, that is supported by OpenGL. The supported formats depend on the installed system graphics card, but most of the time RGBA or BGRA will work. In this case, the graphics pipeline is able to access the image data via DMA. This reduction of copy instructions leads to an improvement in image display time and cpu usage.

To display images, a window is created and set to the current OpenGL context.

//-----------------------------------------------------------------------------
bool OGLDisplayWindow::WindowInit( void )
//-----------------------------------------------------------------------------
{
// Initialization of GLFW
if( !glfwInit() )
{
std::cerr << "GLFW initialization failed" << std::endl;
return false;
}
// create a window using GLFW
pWindow_ = glfwCreateWindow( 1280, 720, title_.c_str(), NULL, NULL );
if( !pWindow_ )
{
std::cerr << "Window creation failed" << std::endl;
glfwTerminate();
return false;
}
// create a valid OpenGL context in the current window
glfwMakeContextCurrent( pWindow_ );
glfwSetWindowPos( pWindow_, 540, 150 );
// Only after creation of a context, glewInit() will work!
if( glewInit() != GLEW_OK )
{
std::cout << "Error! GlewInit() failed..." << std::endl;
return false;
}
std::cout << "Using OpenGL Version: " << glGetString( GL_VERSION ) << std::endl;
glEnable( GL_TEXTURE_2D );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
return true;
}

One texture object is also needed and at least one pixel buffer object. The pixel buffers are now supplied as user managed memory to the image requests.

//-----------------------------------------------------------------------------
class UserSuppliedHeapBuffer
//-----------------------------------------------------------------------------
{
char* pBuf_;
unique_ptr<PixelBuffer> pPB_;
unsigned int bufSize_;
int alignment_;
public:
explicit UserSuppliedHeapBuffer( int bufSize, int alignment ) : pBuf_( nullptr ), bufSize_( bufSize ), alignment_( alignment )
{
if( bufSize_ > 0 )
{
pPB_ = unique_ptr<PixelBuffer>( new PixelBuffer( bufSize_ ) );
reallocate();
}
}
~UserSuppliedHeapBuffer()
{
if( pPB_ )
{
pPB_->Unmap();
}
}
char* getPtr( void )
{
return pBuf_;
}
int getSize( void ) const
{
return bufSize_;
}
char* reallocate( void )
{
pBuf_ = reinterpret_cast<char*>( pPB_->Map() );
assert( isAligned( reinterpret_cast<uintptr_t>( pBuf_ ), static_cast<uintptr_t>( alignment_ ) ) && "OpenGL memory cannot be allocated with a certain alignment, however this buffer according the restrictions applied by the device needs it!" );
return pBuf_;
}
PixelBuffer* getBuffer( void ) const
{
return pPB_.get();
}
};

After receiving a request with an acquired image, the pixel buffer is bound to the texture object. This texture can now be displayed by assigning it to a 2D canvas, that uses the whole window area.

//-----------------------------------------------------------------------------
void Texture::Draw( PixelBuffer* pBuffer )
//-----------------------------------------------------------------------------
{
pBuffer->Bind();
Bind();
glUnmapBuffer( GL_PIXEL_UNPACK_BUFFER );
GLCall( glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, dataFormat_, dataType_, 0 ) );
glBegin( GL_QUADS );
// bottom left
glTexCoord2f( 0.0f, 0.0f );
glVertex2f( -1.0f, 1.0f );
// top left
glTexCoord2f( 0.0f, 1.0f );
glVertex2f( -1.0f, -1.0f );
// top right
glTexCoord2f( 1.0f, 1.0f );
glVertex2f( 1.0f, -1.0f );
// bottom right
glTexCoord2f( 1.0f, 0.0f );
glVertex2f( 1.0f, 1.0f );
glEnd();
}

Please refer to the OpenGL documentation (https://www.opengl.org/) for detailed description of the used OpenGL functions.

OpenGLDisplay.h
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string>
//-----------------------------------------------------------------------------
/// \brief A class that can be used to display images in a window.
/**
* Every instance of this class will create and display its own independent window.
* Internally it uses OpenGL with GLEW and GLFW to display image data.
*/
class OGLDisplayWindow
//-----------------------------------------------------------------------------
{
private:
GLuint width_;
GLuint height_;
std::string title_;
GLFWwindow* pWindow_;
OGLDisplayWindow( const OGLDisplayWindow& ); // do not allow copy constructor
OGLDisplayWindow& operator=( const OGLDisplayWindow& ); // do not allow assignments
public:
/// \brief Creates a new window that can be used to display image data and displays it.
explicit OGLDisplayWindow(
GLuint width,
GLuint height,
/// [in] The title of the window (will be displayed in the windows title bar).
const std::string& title ) : width_( width ), height_( height ), title_( title ), pWindow_( 0 ) {}
/// \brief destroys the display window and frees resources.
~OGLDisplayWindow();
/// \brief Initialises the window and its OpenGL context.
bool WindowInit( void );
void WindowUpdate( void );
void Clear( void );
GLFWwindow* GetContextWindow()
{
return pWindow_;
}
};
//-----------------------------------------------------------------------------
/// \brief A class that can be used to store image data in a pixel buffer.
/**
* Every instance of this class will create its own pixel buffer inside the graphics memory.
*/
class PixelBuffer
//-----------------------------------------------------------------------------
{
private:
GLuint rendererID_;
GLuint size_;
public:
explicit PixelBuffer( unsigned int size );
~PixelBuffer();
void Bind( void );
void* Map( void );
void Unmap( void );
};
//-----------------------------------------------------------------------------
/// \brief A class that can be used to create a texture object.
/**
* Every instance of this class will create a texture with a unique ID to refer to.
*/
class Texture
//-----------------------------------------------------------------------------
{
private:
GLuint rendererID_;
GLint outputFormat_;
GLint dataFormat_;
GLint dataType_;
GLuint width_;
GLuint height_;
void Bind( void );
public:
explicit Texture( GLuint width, GLuint height, GLint dataFormat = GL_RGB, GLint outputFormat = GL_RGB, GLint dataType = GL_UNSIGNED_BYTE );
~Texture();
void Draw( PixelBuffer* pBuffer );
};
OpenGLDisplay.cpp
#include "OpenGLDisplay.h"
#include <iostream>
#ifdef _WIN32
# define ASSERT(x) \
if( !( x ) ) __debugbreak();
# define GLCall(x) \
while( glGetError() != GL_NO_ERROR ); \
x; \
ASSERT( GLLogCall( #x, __FILE__, __LINE__ ) )
//-----------------------------------------------------------------------------
static bool GLLogCall( const char* function, const char* file, int line )
//-----------------------------------------------------------------------------
{
const GLenum err = glGetError();
if( err != GL_NO_ERROR )
{
std::cout << "[OpenGL Error] (" << err << "): " << function << " " << file << ":" << line << std::endl;
}
return ( err == GL_NO_ERROR );
}
#else
# define GLCall(x) x;
#endif
//=============================================================================
//================= Implementation OGLDisplayWindow ===========================
//=============================================================================
//-----------------------------------------------------------------------------
OGLDisplayWindow::~OGLDisplayWindow()
//-----------------------------------------------------------------------------
{
glfwTerminate();
glfwDestroyWindow( pWindow_ );
}
//-----------------------------------------------------------------------------
bool OGLDisplayWindow::WindowInit( void )
//-----------------------------------------------------------------------------
{
// Initialization of GLFW
if( !glfwInit() )
{
std::cerr << "GLFW initialization failed" << std::endl;
return false;
}
// create a window using GLFW
pWindow_ = glfwCreateWindow( 1280, 720, title_.c_str(), NULL, NULL );
if( !pWindow_ )
{
std::cerr << "Window creation failed" << std::endl;
glfwTerminate();
return false;
}
// create a valid OpenGL context in the current window
glfwMakeContextCurrent( pWindow_ );
glfwSetWindowPos( pWindow_, 540, 150 );
// Only after creation of a context, glewInit() will work!
if( glewInit() != GLEW_OK )
{
std::cout << "Error! GlewInit() failed..." << std::endl;
return false;
}
std::cout << "Using OpenGL Version: " << glGetString( GL_VERSION ) << std::endl;
glEnable( GL_TEXTURE_2D );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
return true;
}
//-----------------------------------------------------------------------------
void OGLDisplayWindow::WindowUpdate( void )
//-----------------------------------------------------------------------------
{
int width;
int height;
glfwGetWindowSize( pWindow_, &width, &height );
glViewport( 0, 0, width, height );
glfwSwapBuffers( pWindow_ );
glfwPollEvents();
}
//-----------------------------------------------------------------------------
void OGLDisplayWindow::Clear( void )
//-----------------------------------------------------------------------------
{
glClearColor( 0.5f, 0.8f, 0.5f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
}
//=============================================================================
//================= Implementation PixelBuffer ================================
//=============================================================================
//-----------------------------------------------------------------------------
PixelBuffer::PixelBuffer( unsigned int size ) : size_( ( GLuint )( size ) )
//-----------------------------------------------------------------------------
{
glGenBuffers( 1, &rendererID_ );
}
//-----------------------------------------------------------------------------
PixelBuffer::~PixelBuffer()
//-----------------------------------------------------------------------------
{
glDeleteBuffers( 1, &rendererID_ );
}
//-----------------------------------------------------------------------------
void PixelBuffer::Bind( void )
//-----------------------------------------------------------------------------
{
glBindBuffer( GL_PIXEL_UNPACK_BUFFER, rendererID_ );
}
//-----------------------------------------------------------------------------
void* PixelBuffer::Map( void )
//-----------------------------------------------------------------------------
{
Bind();
glBufferData( GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_DYNAMIC_DRAW );
return glMapBuffer( GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY );
}
//-----------------------------------------------------------------------------
void PixelBuffer::Unmap( void )
//-----------------------------------------------------------------------------
{
Bind();
glUnmapBuffer( GL_PIXEL_UNPACK_BUFFER );
}
//=============================================================================
//================= Implementation Texture ====================================
//=============================================================================
//-----------------------------------------------------------------------------
Texture::Texture( GLuint width, GLuint height, GLint dataFormat /*= GL_RGB*/, GLint outputFormat /*= GL_RGB*/, GLint dataType /*= GL_UNSIGNED_BYTE*/ ) : rendererID_( 0 ), outputFormat_( outputFormat ), dataFormat_( dataFormat ), dataType_( dataType ), width_( width ), height_( height )
//-----------------------------------------------------------------------------
{
glGenTextures( 1, &rendererID_ );
Bind();
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexImage2D( GL_TEXTURE_2D, 0, outputFormat_, width_, height_, 0, dataFormat_, dataType_, 0 );
}
//-----------------------------------------------------------------------------
Texture::~Texture()
//-----------------------------------------------------------------------------
{
glDeleteTextures( 1, &rendererID_ );
}
//-----------------------------------------------------------------------------
void Texture::Bind( void )
//-----------------------------------------------------------------------------
{
glBindTexture( GL_TEXTURE_2D, rendererID_ );
}
//-----------------------------------------------------------------------------
void Texture::Draw( PixelBuffer* pBuffer )
//-----------------------------------------------------------------------------
{
pBuffer->Bind();
Bind();
glUnmapBuffer( GL_PIXEL_UNPACK_BUFFER );
GLCall( glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, width_, height_, dataFormat_, dataType_, 0 ) );
glBegin( GL_QUADS );
// bottom left
glTexCoord2f( 0.0f, 0.0f );
glVertex2f( -1.0f, 1.0f );
// top left
glTexCoord2f( 0.0f, 1.0f );
glVertex2f( -1.0f, -1.0f );
// top right
glTexCoord2f( 1.0f, 1.0f );
glVertex2f( 1.0f, -1.0f );
// bottom right
glTexCoord2f( 1.0f, 0.0f );
glVertex2f( 1.0f, 1.0f );
glEnd();
}
CaptureToOpenGLMemory.cpp
#include <iostream>
#include <memory>
#include <apps/Common/exampleHelper.h>
#include <common/minmax.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
#include <apps/CaptureToOpenGLMemory/OpenGLDisplay.h>
#include <chrono>
using namespace std;
using namespace mvIMPACT::acquire;
static bool s_boTerminated = false;
//=============================================================================
//================= Data type definitions =====================================
//=============================================================================
//-----------------------------------------------------------------------------
// the buffer we pass to the device driver must be aligned according to its requirements
// As we can't allocate aligned heap memory we will align it 'by hand'
class UserSuppliedHeapBuffer
//-----------------------------------------------------------------------------
{
char* pBuf_;
unique_ptr<PixelBuffer> pPB_;
unsigned int bufSize_;
public:
explicit UserSuppliedHeapBuffer( int bufSize ) : pBuf_( nullptr ), bufSize_( bufSize )
{
if( bufSize_ > 0 )
{
pPB_ = unique_ptr<PixelBuffer>( new PixelBuffer( bufSize_ ) );
pBuf_ = reinterpret_cast<char*>( pPB_->Map() );
}
}
~UserSuppliedHeapBuffer()
{
if( pPB_ )
{
pPB_->Unmap();
}
}
char* getPtr( void )
{
return pBuf_;
}
int getSize( void ) const
{
return bufSize_;
}
char* reallocate( void )
{
pBuf_ = reinterpret_cast<char*>( pPB_->Map() );
return getPtr();
}
PixelBuffer* getBuffer( void ) const
{
return pPB_.get();
}
};
using CaptureBufferContainer = std::vector<shared_ptr<UserSuppliedHeapBuffer>>;
//-----------------------------------------------------------------------------
struct CaptureParameter
//-----------------------------------------------------------------------------
{
Device* pDev;
Statistics statistics;
int bufferSize;
int bufferAlignment;
int bufferPitch;
CaptureBufferContainer buffers;
GLenum bufferDataFormat;
GLenum outputImageFormat;
unique_ptr<OGLDisplayWindow> pDisplay;
Texture* pTex;
explicit CaptureParameter( Device* p ) : pDev{ p }, fi{ p }, irc{ p }, statistics{ p },
bufferSize{ 0 }, bufferAlignment{ 0 }, bufferPitch{ 0 }, bufferDataFormat( GL_BGRA ), outputImageFormat( GL_RGBA ), pDisplay{ nullptr }, pTex{ nullptr }
{}
void initPixelFormat( TImageBufferPixelFormat imageBufferPixelFormat )
{
switch( imageBufferPixelFormat )
{
bufferDataFormat = GL_BGRA;
outputImageFormat = GL_RGBA;
break;
case ibpfMono8:
bufferDataFormat = GL_RED;
outputImageFormat = GL_LUMINANCE8;
break;
bufferDataFormat = GL_BGR;
outputImageFormat = GL_RGB;
break;
default:
std::cout << "Unsupported imageBufferPixelFormat used in function " << __FUNCTION__ << ". Going to exit now!" << std::endl;
exit( 42 );
}
}
};
int createCaptureBuffer( FunctionInterface& fi, CaptureBufferContainer& buffers, const int bufferSize, const int bufferAlignment, const int bufferPitch, unsigned int requestNr );
int createCaptureBuffers( FunctionInterface& fi, CaptureBufferContainer& buffers, const int bufferSize, const int bufferAlignment, const int bufferPitch );
void freeCaptureBuffer( FunctionInterface& fi, CaptureBufferContainer& buffers, unsigned int requestNr );
void freeCaptureBuffers( FunctionInterface& fi, CaptureBufferContainer& buffers );
void runLiveLoop( CaptureParameter& captureParams );
//-----------------------------------------------------------------------------
int createCaptureBuffer( FunctionInterface& fi, CaptureBufferContainer& buffers, const int bufferSize, const int /*bufferPitch*/, unsigned int requestNr )
//-----------------------------------------------------------------------------
{
int functionResult = DMR_NO_ERROR;
Request* pRequest = fi.getRequest( requestNr );
shared_ptr<UserSuppliedHeapBuffer> pBuffer = make_shared<UserSuppliedHeapBuffer>( bufferSize );
if( ( functionResult = pRequest->attachUserBuffer( pBuffer->getPtr(), pBuffer->getSize() ) ) != DMR_NO_ERROR )
{
cout << "An error occurred while attaching a buffer to request number " << requestNr << ": " << ImpactAcquireException::getErrorCodeAsString( functionResult ) << "." << endl;
return -1;
}
buffers.push_back( pBuffer );
return 0;
}
//-----------------------------------------------------------------------------
int createCaptureBuffers( FunctionInterface& fi, CaptureBufferContainer& buffers, const int bufferSize, const int bufferPitch )
//-----------------------------------------------------------------------------
{
freeCaptureBuffers( fi, buffers );
unsigned int requestCnt = fi.requestCount();
for( unsigned int i = 0; i < requestCnt; i++ )
{
try
{
const int result = createCaptureBuffer( fi, buffers, bufferSize, bufferPitch, i );
if( result != 0 )
{
freeCaptureBuffers( fi, buffers );
return result;
}
}
catch( const ImpactAcquireException& e )
{
freeCaptureBuffers( fi, buffers );
return e.getErrorCode();
}
}
return 0;
}
//-----------------------------------------------------------------------------
void freeCaptureBuffer( FunctionInterface& fi, CaptureBufferContainer& buffers, unsigned int requestNr )
//-----------------------------------------------------------------------------
{
try
{
int functionResult = DMR_NO_ERROR;
Request* pRequest = fi.getRequest( requestNr );
if( pRequest->imageMemoryMode.read() == rimmUser )
{
if( ( functionResult = pRequest->detachUserBuffer() ) != DMR_NO_ERROR )
{
cout << "An error occurred while detaching a buffer from request number " << requestNr << " : " << ImpactAcquireException::getErrorCodeAsString( functionResult ) << "." << endl;
}
}
const void* const pAddr = pRequest->imageData.read();
CaptureBufferContainer::iterator it = find_if( buffers.begin(), buffers.end(), [pAddr]( const shared_ptr<UserSuppliedHeapBuffer>& buffer )
{
return pAddr == buffer->getPtr();
} );
if( it != buffers.end() )
{
buffers.erase( it );
}
}
catch( const ImpactAcquireException& e )
{
cout << "An error occurred while changing the mode of request number " << requestNr << ": " << e.getErrorCodeAsString() << "." << endl;
}
}
//-----------------------------------------------------------------------------
void freeCaptureBuffers( FunctionInterface& fi, CaptureBufferContainer& buffers )
//-----------------------------------------------------------------------------
{
const unsigned int requestCnt = fi.requestCount();
for( unsigned int i = 0; i < requestCnt; i++ )
{
freeCaptureBuffer( fi, buffers, i );
}
if( !buffers.empty() )
{
cout << "Error! The buffer container should be empty now but still contains " << buffers.size() << " elements!" << endl;
}
}
//-----------------------------------------------------------------------------
void liveLoop( CaptureParameter* pParameter )
//-----------------------------------------------------------------------------
{
// 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.
while( ( result = static_cast<TDMR_ERROR>( pParameter->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( pParameter->pDev, pParameter->fi );
// run thread loop
unsigned int cnt = {0};
const unsigned int timeout_ms = {500};
Request* pRequest = nullptr;
// 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.
Request* pPreviousRequest = nullptr;
CaptureBufferContainer::iterator it;
shared_ptr<UserSuppliedHeapBuffer> previousBuffer;
while( !s_boTerminated )
{
// wait for results from the default capture queue
const int requestNr = pParameter->fi.imageRequestWaitFor( timeout_ms );
pRequest = pParameter->fi.isRequestNrValid( requestNr ) ? pParameter->fi.getRequest( requestNr ) : 0;
if( pRequest != nullptr )
{
if( pRequest->isOK() )
{
++cnt;
// here we can display some statistical information every 100th image
if( cnt % 100 == 0 )
{
cout << "Info from " << pParameter->pDev->serial.read()
<< ": " << pParameter->statistics.framesPerSecond.name() << ": " << pParameter->statistics.framesPerSecond.readS()
<< ", " << pParameter->statistics.errorCount.name() << ": " << pParameter->statistics.errorCount.readS()
<< ", " << pParameter->statistics.captureTime_s.name() << ": " << pParameter->statistics.captureTime_s.readS()
<< ", CaptureDimension: " << pRequest->imageWidth.read() << "x" << pRequest->imageHeight.read() << "(" << pRequest->imagePixelFormat.readS() << ")" << endl;
}
void* const pAddr = pRequest->imageData.read();
it = find_if( pParameter->buffers.begin(), pParameter->buffers.end(), [pAddr]( const shared_ptr<UserSuppliedHeapBuffer>& buffer )
{
return pAddr == buffer->getPtr();
} );
pParameter->pTex->Draw( ( *it )->getBuffer() );
pParameter->pDisplay->WindowUpdate();
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
if( pPreviousRequest != nullptr )
{
// this image has been displayed thus the buffer is no longer needed...
pPreviousRequest->unlock();
int functionResult = DMR_NO_ERROR;
if( ( functionResult = pPreviousRequest->detachUserBuffer() ) != DMR_NO_ERROR )
{
cout << "Error: Could not detach the buffer from the previous request. Error: " << ImpactAcquireException::getErrorCodeAsString( functionResult ) << "(" << functionResult << ")" << endl;
glfwTerminate();
manuallyStopAcquisitionIfNeeded( pParameter->pDev, pParameter->fi );
return;
}
if( ( functionResult = pPreviousRequest->attachUserBuffer( previousBuffer->reallocate(), previousBuffer->getSize() ) ) != DMR_NO_ERROR )
{
cout << "Error: Could not attach a new buffer to the previous request. Error: " << ImpactAcquireException::getErrorCodeAsString( functionResult ) << "(" << functionResult << ")" << endl;
glfwTerminate();
manuallyStopAcquisitionIfNeeded( pParameter->pDev, pParameter->fi );
return;
}
}
previousBuffer = *it;
pPreviousRequest = pRequest;
// send a new image request into the capture queue
pParameter->fi.imageRequestSingle();
}
if( glfwWindowShouldClose( pParameter->pDisplay->GetContextWindow() ) )
{
s_boTerminated = true;
}
}
glfwTerminate();
manuallyStopAcquisitionIfNeeded( pParameter->pDev, pParameter->fi );
// 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( pRequest != nullptr )
{
pRequest->unlock();
}
// clear all queues
pParameter->fi.imageRequestReset( 0, 0 );
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
unsigned int mode = 4;
Device* pDev = getDeviceFromUserInput( devMgr );
if( pDev == nullptr )
{
cout << "Unable to continue! Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
while( mode > 3 )
{
std::cout << "Select Mode:" << std::endl
<< "[0] 32-bit RGB" << std::endl
<< "[1] 24-bit RGB" << std::endl
<< "[2] 8-bit Mono" << std::endl
<< "[3] EXIT the application" << std::endl;
std::cin >> mode;
std::cin.get();
if( mode == 3 )
{
return 0;
}
}
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;
}
CaptureParameter captureParams( pDev );
ImageDestination id( pDev );
switch( mode )
{
case 0:
id.pixelFormat.write( idpfRGBx888Packed );
captureParams.initPixelFormat( ibpfRGBx888Packed );
break;
case 1:
id.pixelFormat.write( idpfRGB888Packed );
captureParams.initPixelFormat( ibpfRGB888Packed );
break;
case 2:
id.pixelFormat.write( idpfMono8 );
captureParams.initPixelFormat( ibpfMono8 );
break;
}
GLuint width = 640;
GLuint height = 480;
if( pDev->interfaceLayout.read() == dilGenICam )
{
std::cout << "GenICam device detected" << std::endl;
if( ifc.width.isValid() && ifc.height.isValid() )
{
width = GLuint( ifc.width.read() );
height = GLuint( ifc.height.read() );
}
else
{
cout << "ERROR: Cannot read width and height from device!" << endl;
return 1;
}
}
else
{
CameraSettingsBase csb( pDev );
height = csb.aoiHeight.read();
width = csb.aoiWidth.read();
}
std::cout << width << "x" << height << std::endl;
captureParams.pDisplay = unique_ptr<OGLDisplayWindow>( new OGLDisplayWindow( GLuint( width ), GLuint( height ), std::string( "CaptureToOpenGLMemory" ) ) );
if( !captureParams.pDisplay->WindowInit() )
{
std::cerr << "ERROR: OpenGL Window not initialized." << std::endl;
}
glfwSetWindowAspectRatio( captureParams.pDisplay->GetContextWindow(), int( width ), int( height ) );
captureParams.pTex = new Texture( GLuint( width ), GLuint( height ), captureParams.bufferDataFormat, captureParams.outputImageFormat, GL_UNSIGNED_BYTE );
//// find out the size of the resulting buffer by requesting a dummy request
int bufferAlignment = { 0 };
Request* pCurrentCaptureBufferLayout = nullptr;
int result = captureParams.fi.getCurrentCaptureBufferLayout( captureParams.irc, &pCurrentCaptureBufferLayout, &bufferAlignment );
if( result != 0 )
{
cout << "An error occurred while querying the current capture buffer layout for device " << captureParams.pDev->serial.read()
<< "(error code: " << ImpactAcquireException::getErrorCodeAsString( result ) << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
int bufferSize = pCurrentCaptureBufferLayout->imageSize.read() + pCurrentCaptureBufferLayout->imageFooterSize.read();
int bufferPitch = pCurrentCaptureBufferLayout->imageLinePitch.read();
cout << "Buffer Data: Size " << bufferSize << ", Pitch " << bufferPitch << endl;
result = createCaptureBuffers( captureParams.fi, captureParams.buffers, bufferSize, bufferPitch );
if( result != 0 )
{
cout << "An error occurred while setting up the user supplied buffers for device " << captureParams.pDev->serial.read()
<< "(error code: " << ImpactAcquireException::getErrorCodeAsString( result ) << ")." << endl
<< "Press [ENTER] to end the application..." << endl;
cin.get();
return 1;
}
cout << "**************************************************************************************" << endl
<< " Acquisition started. Close the display window to end the application." << endl
<< "**************************************************************************************" << endl << endl;
liveLoop( &captureParams );
pDev->close();
return 0;
}
A base class for camera related settings(Device specific interface layout only).
Definition: mvIMPACT_acquire.h:18394
Grants access to devices that can be operated by this software interface.
Definition: mvIMPACT_acquire.h:6964
This class and its functions represent an actual device detected by this interface in the current sys...
Definition: mvIMPACT_acquire.h:5948
PropertyS serial
A string property (read-only) containing the serial number of this device.
Definition: mvIMPACT_acquire.h:6351
void close(void)
Closes an opened device.
Definition: mvIMPACT_acquire.h:6090
void open(void)
Opens a device.
Definition: mvIMPACT_acquire.h:6238
PropertyIDeviceInterfaceLayout interfaceLayout
An enumerated integer property which can be used to define which interface layout shall be used when ...
Definition: mvIMPACT_acquire.h:6444
ZYX read(int index=0) const
Reads a value from a property.
Definition: mvIMPACT_acquire.h:4170
The function interface to devices supported by this interface.
Definition: mvIMPACT_acquire.h:10458
unsigned int requestCount(void) const
Returns the number of available request objects.
Definition: mvIMPACT_acquire.h:11661
Request * getRequest(int nr) const
Returns a pointer to the desired mvIMPACT::acquire::Request.
Definition: mvIMPACT_acquire.h:10923
Category for Image Format Control features.
Definition: mvIMPACT_acquire_GenICam.h:1129
Properties to define the format of resulting images.
Definition: mvIMPACT_acquire.h:12062
A helper class to control the way an image request will be processed.
Definition: mvIMPACT_acquire.h:10061
A base class for exceptions generated by mvIMPACT Acquire.
Definition: mvIMPACT_acquire.h:248
std::string getErrorCodeAsString(void) const
Returns a string representation of the error associated with the exception.
Definition: mvIMPACT_acquire.h:280
int getErrorCode(void) const
Returns a unique numerical representation for this error.
Definition: mvIMPACT_acquire.h:267
void * read(int index=0) const
Reads a value from a property.
Definition: mvIMPACT_acquire.h:5012
std::string read(int index=0) const
Reads a value from a property.
Definition: mvIMPACT_acquire.h:5159
std::string readS(int index=0, const std::string &format="") const
Reads data from this property as a string.
Definition: mvIMPACT_acquire.h:3213
Contains information about a captured buffer.
Definition: mvIMPACT_acquire.h:8423
PropertyI imageHeight
An integer property (read-only) containing the height of the image in pixels.
Definition: mvIMPACT_acquire.h:10035
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition: mvIMPACT_acquire.h:9212
PropertyIRequestResult requestResult
An enumerated integer property (read-only) defining the result of this request.
Definition: mvIMPACT_acquire.h:9515
PropertyI imageSize
An integer property (read-only) containing the size (in bytes) of the whole image.
Definition: mvIMPACT_acquire.h:9906
PropertyI imageWidth
An integer property (read-only) containing the width of the image in pixels.
Definition: mvIMPACT_acquire.h:10024
PropertyIRequestImageMemoryMode imageMemoryMode
An enumerated integer property (read-only) containing the memory mode used for this request.
Definition: mvIMPACT_acquire.h:9832
int attachUserBuffer(void *pBuf, int bufSize)
Convenience function to attach a user supplied buffer to a mvIMPACT::acquire::Request object.
Definition: mvIMPACT_acquire.h:9403
PropertyIImageBufferPixelFormat imagePixelFormat
An enumerated integer property (read-only) containing the pixel format of this image.
Definition: mvIMPACT_acquire.h:9840
PropertyPtr imageData
A pointer property (read-only) containing the start address of the image data.
Definition: mvIMPACT_acquire.h:9893
int detachUserBuffer(void)
Convenience function to detach a user supplied buffer from a mvIMPACT::acquire::Request object.
Definition: mvIMPACT_acquire.h:9495
int unlock(void)
Unlocks the request for the driver again.
Definition: mvIMPACT_acquire.h:9352
PropertyI imageLinePitch
An integer property (read-only) containing the offset (in bytes) to the next line of each channel bel...
Definition: mvIMPACT_acquire.h:9966
PropertyI imageFooterSize
An integer property (read-only) containing the size (in bytes) of the footer associated with this ima...
Definition: mvIMPACT_acquire.h:9921
Contains basic statistical information.
Definition: mvIMPACT_acquire.h:14186
TDMR_ERROR
Errors reported by the device manager.
Definition: mvDriverBaseEnums.h:2187
TImageBufferPixelFormat
Valid image buffer pixel formats.
Definition: TImageBufferPixelFormat.h:35
@ DMR_NO_ERROR
The function call was executed successfully.
Definition: mvDriverBaseEnums.h:2192
@ ibpfRGB888Packed
The image will be transferred as an RGB image with 24 bit per pixel.
Definition: TImageBufferPixelFormat.h:140
@ ibpfMono8
A single channel 8 bit per pixel format.
Definition: TImageBufferPixelFormat.h:39
@ ibpfRGBx888Packed
A three channel RGB image with 32 bit per pixel containing one fill byte per pixel.
Definition: TImageBufferPixelFormat.h:59
This namespace contains classes and functions belonging to the image acquisition module of this SDK.
Definition: mvImageBuffer.h:41