Balluff - BVS CA-SF Technical Documentation
Working with LUTValueAll

Working with the LUTValueAll feature requires a detailed understanding on both Endianess and the cameras internal format for storing LUT data. LUTValueAll typically references the same section in the cameras memory as when accessing the LUT via the features LUTIndex and LUTValue.

LUT data can either be written to a device like this (C++ syntax):

const size_t LUT_VALUE_COUNT = 256;
int64_type LUTData[LUT_VALUE_COUNT] = getLUTDataToWriteToTheDevice();
mvIMPACT::acquire::GenICam::LUTControl lut(getDevicePointerFromSomewhere());
for(int64_type i=0; i< static_cast<int64_type>(LUT_VALUE_COUNT); i++ )
{
  lut.LUTIndex.write( i );
  lut.LUTValue.write( LUTData[i] );
}

When using this approach all the Endianess related issues will be handled completely by the GenICam runtime library. So this code is straight forward and easy to understand but might be slower than desired as it requires a lot of direct register accesses to the device.

In order to allow a fast efficient way to read/write LUT data from/to a device the LUTValueAll feature has been introduced. When using this feature the complete LUT can be written to a device like this:

const size_t LUT_VALUE_COUNT = 256;
int LUTData[LUT_VALUE_COUNT] = getLUTDataToWriteToTheDevice();
mvIMPACT::acquire::GenICam::LUTControl lut(getDevicePointerFromSomewhere());
std::string buf(reinterpret_cast<std::string::value_type*>(&LUTData), sizeof(LUTData));
lut.LUTValueAll.writeBinary( buf );

BUT as this simply writes a raw block of memory to the device it suddenly becomes important to know exactly how the LUT data is stored inside the camera. This includes:

  • The size of one individual LUT entry (this could be anything from 1 up to 8 bytes)
  • The Endianess of the device
  • The Endianess of the host system used for sending/receiving the LUT data

The first item has impact on how the memory must be allocated for receiving/sending LUT data. For example when the LUT data on the device uses a 'one 32-bit integer per LUT entry with 256 entries' layout then of course this is needed on the host system:

const size_t LUT_VALUE_COUNT = 256;
int LUTData[LUT_VALUE_COUNT];

When the Endianess of the host system differs from the Endianess used by the device the application communicates with, then before sending data assembled on the host might require Endianess swapping. For the example from above this would e.g. require something like this:

#define SWAP_32(l) \
  ((((l) & 0xff000000) >> 24) | \
   (((l) & 0x00ff0000) >> 8)  | \
   (((l) & 0x0000ff00) << 8)  | \
   (((l) & 0x000000ff) << 24))

void fn()
{
 const size_t LUT_VALUE_COUNT = 256;
 int LUTData[LUT_VALUE_COUNT] = getLUTDataToWriteToTheDevice();
 mvIMPACT::acquire::GenICam::LUTControl lut(getDevicePointerFromSomewhere());
 for( size_t i=0; i<LUT_VALUE_COUNT; i++ )
 {
  LUTData[i] = SWAP_32(LUTData[i]);
 }
 std::string buf(reinterpret_cast<std::string::value_type*>(&LUTData), sizeof(LUTData));
 lut.LUTValueAll.writeBinary( buf );
}

For details on how the LUT memory is organized for certain sensors please refers to the Sensor Overview. Please note that all BVS CA-GX0 and BVS CA-GX2 devices are using Big Endian while almost any Windows or Linux distribution on the market uses Little Endian, thus the swapping of the data will most certainly be necessary when using the LUTValueAll feature.