Impact Acquire SDK C++
SingleCaptureStorage.cpp

The SingleCaptureStorage program is based on the SingleCapture.cpp example. The example snaps a single image and saves it as a BMP file.

Program location
The source file SingleCaptureStorage.cpp can be found under:
%INSTALLDIR%\apps\SingleCaptureStorage\
Note
If you have installed the package without example applications, this file 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.
SingleCaptureStorage example:
  1. Opens a Balluff device.
  2. Snaps an image (without display using Linux).
  3. Saves the image as single.bmp.
Console Output
[0]: 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.
The device BF000306 has been opened.
Storing the image as "single.bmp"
Press [ENTER] to end the application
How it works
The image acquisition is the same as in the SingleCapture.cpp example.

The interesting thing about this example is to see how to save an image into a bitmap file.

This is done by calling the following function:

SaveBMP( const string& filename, const char* pData, int XSize, int YSize, int pitch, int bitsPerPixel )

The SaveBMP function is Windows® specific and is a standard example how to save a BMP. The developer calls this function and passes some parameters. The parameters are the filename, the pointer to the beginning of the image data, the image width and height, the pitch and the bits per pixel. Programmers working on other platforms might have to replace the system specific function calls by the appropriate calls specific on their platform.

Note
Please notice, that only 32-bit BMPs are supported.

This is the function storing the image:

//-----------------------------------------------------------------------------
int SaveBMP( const string& filename, const char* pData, int XSize, int YSize, int pitch, int bitsPerPixel )
//------------------------------------------------------------------------------
{
static const WORD PALETTE_ENTRIES = 256;
if( pData )
{
FILE* pFile = mv_fopen_s( filename.c_str(), "wb" );
if( pFile )
{
BITMAPINFOHEADER bih;
BITMAPFILEHEADER bfh;
WORD linelen = static_cast<WORD>( ( XSize * bitsPerPixel + 31 ) / 32 * 4 ); // DWORD aligned
int YPos;
int YStart = 0;
memset( &bfh, 0, sizeof( BITMAPFILEHEADER ) );
memset( &bih, 0, sizeof( BITMAPINFOHEADER ) );
bfh.bfType = 0x4d42;
bfh.bfSize = sizeof( bih ) + sizeof( bfh ) + sizeof( RGBQUAD ) * PALETTE_ENTRIES + static_cast<LONG>( linelen ) * static_cast<LONG>( YSize );
bfh.bfOffBits = sizeof( bih ) + sizeof( bfh ) + sizeof( RGBQUAD ) * PALETTE_ENTRIES;
bih.biSize = sizeof( bih );
bih.biWidth = XSize;
bih.biHeight = YSize;
bih.biPlanes = 1;
bih.biBitCount = static_cast<WORD>( bitsPerPixel );
bih.biSizeImage = static_cast<DWORD>( linelen ) * static_cast<DWORD>( YSize );
if( ( fwrite( &bfh, sizeof( bfh ), 1, pFile ) == 1 ) && ( fwrite( &bih, sizeof( bih ), 1, pFile ) == 1 ) )
{
RGBQUAD rgbQ;
for( int i = 0; i < PALETTE_ENTRIES; i++ )
{
rgbQ.rgbRed = static_cast<BYTE>( i );
rgbQ.rgbGreen = static_cast<BYTE>( i );
rgbQ.rgbBlue = static_cast<BYTE>( i );
rgbQ.rgbReserved = static_cast<BYTE>( 0 );
fwrite( &rgbQ, sizeof( rgbQ ), 1, pFile );
}
for( YPos = YStart + YSize - 1; YPos >= YStart; YPos-- )
{
if( fwrite( &pData[YPos * pitch], linelen, 1, pFile ) != 1 )
{
cout << "SaveBmp: ERR_WRITE_FILE: " << filename << endl;
}
}
}
else
{
cout << "SaveBmp: ERR_WRITE_FILE: " << filename << endl;
}
fclose( pFile );
}
else
{
cout << "SaveBmp: ERR_CREATE_FILE: " << filename << endl;
}
}
else
{
cout << "SaveBmp: ERR_DATA_INVALID:" << filename << endl;
}
return 0;
}

The example can be extended for automatic pixel format change (8 bits per pixel) to avoid the message

The BMP format does not support a data depth of xx bits per pixel

by adding this code to the main program:

//include <mvIMPACT_CPP/mvIMPACT_acquire_GenICam.h>
..
pDev->interfaceLayout.write( dilGenICam );
//open the device
//switch to Bayer pixel format if this is a color camera, otherwise Mono8 will be configured
GenICam::DeviceControl dc( pDev );
GenICam::ImageFormatControl ifc( pDev );
if( ( dc.mvDeviceSensorColorMode.isValid() ) && ( dc.mvDeviceSensorColorMode.readS() == "BayerMosaic" ) )
{
if( ifc.pixelColorFilter.isValid() )
{
const string parity = ifc.pixelColorFilter.readS();
if( parity == "BayerBG" )
{
ifc.pixelFormat.writeS( "BayerBG8" );
}
else if( parity == "BayerGB" )
{
ifc.pixelFormat.writeS( "BayerGB8" );
}
else if( parity == "BayerRG" )
{
ifc.pixelFormat.writeS( "BayerRG8" );
}
else if( parity == "BayerGR" )
{
ifc.pixelFormat.writeS( "BayerGR8" );
}
else
{
cout << "Undefined BayerMosaicParity! Terminating..." << endl;
exit( 42 );
}
}
else
{
cout << "Undefined BayerMosaicParity! Terminating..." << endl;
exit( 42 );
}
}
else
{
ifc.pixelFormat.writeS( "Mono8" );
}
..
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-05-04
//
// 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 <apps/Common/exampleHelper.h>
#include <common/crt/mvstdio.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
#ifdef _WIN32
# include <mvDisplay/Include/mvIMPACT_acquire_display.h>
# define USE_DISPLAY
#endif // #ifdef _WIN32
#include <iostream>
#include <string>
using namespace std;
using namespace mvIMPACT::acquire;
#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__)
# include <stdint.h>
# include <stdio.h>
typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef bool BOOLEAN;
# ifdef __GNUC__
# define BMP_ATTR_PACK __attribute__((packed)) __attribute__ ((aligned (2)))
# else
# define BMP_ATTR_PACK
# endif // #ifdef __GNUC__
typedef struct tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} BMP_ATTR_PACK RGBQUAD;
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BMP_ATTR_PACK BITMAPINFOHEADER, *PBITMAPINFOHEADER;
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BMP_ATTR_PACK BITMAPFILEHEADER, *PBITMAPFILEHEADER;
#endif // #if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__)
//-----------------------------------------------------------------------------
int SaveBMP( const string& filename, const char* pData, int XSize, int YSize, int pitch, int bitsPerPixel )
//-----------------------------------------------------------------------------
{
static const WORD PALETTE_ENTRIES = 256;
if( pData )
{
FILE* pFile = mv_fopen_s( filename.c_str(), "wb" );
if( pFile )
{
BITMAPINFOHEADER bih;
BITMAPFILEHEADER bfh;
WORD linelen = static_cast<WORD>( ( XSize * bitsPerPixel + 31 ) / 32 * 4 ); // DWORD aligned
int YPos;
int YStart = 0;
memset( &bfh, 0, sizeof( BITMAPFILEHEADER ) );
memset( &bih, 0, sizeof( BITMAPINFOHEADER ) );
bfh.bfType = 0x4d42;
bfh.bfSize = sizeof( bih ) + sizeof( bfh ) + sizeof( RGBQUAD ) * PALETTE_ENTRIES + static_cast<LONG>( linelen ) * static_cast<LONG>( YSize );
bfh.bfOffBits = sizeof( bih ) + sizeof( bfh ) + sizeof( RGBQUAD ) * PALETTE_ENTRIES;
bih.biSize = sizeof( bih );
bih.biWidth = XSize;
bih.biHeight = YSize;
bih.biPlanes = 1;
bih.biBitCount = static_cast<WORD>( bitsPerPixel );
bih.biSizeImage = static_cast<DWORD>( linelen ) * static_cast<DWORD>( YSize );
if( ( fwrite( &bfh, sizeof( bfh ), 1, pFile ) == 1 ) && ( fwrite( &bih, sizeof( bih ), 1, pFile ) == 1 ) )
{
RGBQUAD rgbQ;
for( int i = 0; i < PALETTE_ENTRIES; i++ )
{
rgbQ.rgbRed = static_cast<BYTE>( i );
rgbQ.rgbGreen = static_cast<BYTE>( i );
rgbQ.rgbBlue = static_cast<BYTE>( i );
rgbQ.rgbReserved = static_cast<BYTE>( 0 );
fwrite( &rgbQ, sizeof( rgbQ ), 1, pFile );
}
for( YPos = YStart + YSize - 1; YPos >= YStart; YPos-- )
{
if( fwrite( &pData[YPos * pitch], linelen, 1, pFile ) != 1 )
{
cout << "SaveBmp: ERR_WRITE_FILE: " << filename << endl;
}
}
}
else
{
cout << "SaveBmp: ERR_WRITE_FILE: " << filename << endl;
}
fclose( pFile );
}
else
{
cout << "SaveBmp: ERR_CREATE_FILE: " << filename << endl;
}
}
else
{
cout << "SaveBmp: ERR_DATA_INVALID:" << filename << endl;
}
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;
}
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.getErrorCode() << "). Press any key to end the application..." << endl;
cout << "Press [ENTER] to end the application" << endl;
cin.get();
return 1;
}
cout << "The device " << pDev->serial.read() << " has been opened." << endl;
FunctionInterface fi( pDev );
// send a request to the default request queue of the device and wait for the result.
fi.imageRequestSingle();
manuallyStartAcquisitionIfNeeded( pDev, fi );
// Wait for results from the default capture queue by passing a timeout (The maximum time allowed
// for the application to wait for a Result). Infinity value: -1, positive value: The time to wait in milliseconds.
// 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.
// Once the device is configured for triggered image acquisition and the timeout elapsed before
// the device has been triggered this might happen as well.
// 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.
const int iMaxWaitTime_ms = 500;
// wait for results from the default capture queue
int requestNr = fi.imageRequestWaitFor( iMaxWaitTime_ms );
// check if the image has been captured without any problems
if( !fi.isRequestNrValid( requestNr ) )
{
// If the error code is -2119(DEV_WAIT_FOR_REQUEST_FAILED), the documentation will provide
// additional information under TDMR_ERROR in the interface reference
cout << "imageRequestWaitFor failed maybe the timeout value has been too small?" << endl;
return 1;
}
const Request* pRequest = fi.getRequest( requestNr );
if( !pRequest->isOK() )
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
return 1;
}
// everything went well. Display the result
#ifdef USE_DISPLAY
ImageDisplayWindow displayWindow( "mvIMPACT_acquire sample" );
displayWindow.GetImageDisplay().SetImage( pRequest );
displayWindow.GetImageDisplay().Update();
#endif // #ifdef USE_DISPLAY
// save the image to BMP only for compliant PixelPitch
switch( ( pRequest->imagePixelPitch.read() * 8 ) )
{
case 8:
case 24:
case 32:
{
const string filename( "single.bmp" );
cout << "Storing the image as \"" << filename << "\"" << endl;
SaveBMP( filename, reinterpret_cast<char*>( pRequest->imageData.read() ), pRequest->imageWidth.read(), pRequest->imageHeight.read(), pRequest->imageLinePitch.read(), pRequest->imagePixelPitch.read() * 8 );
break;
}
default:
cout << "The BMP format does not support a data depth of " << ( pRequest->imagePixelPitch.read() * 8 ) << " bits per pixel" << endl;
}
// unlock the buffer to let the driver know that you no longer need this buffer
fi.imageRequestUnlock( requestNr );
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
A base class for exceptions generated by Impact Acquire.
Definition mvIMPACT_acquire.h:256
int getErrorCode(void) const
Returns a unique numerical representation for this error.
Definition mvIMPACT_acquire.h:275
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
A class that can be used to display images in a window.
Definition mvIMPACT_acquire_display.h:606
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