/***********************************************************************************
*
* Itala API - Copyright (C) 2022 Opto Engineering
*
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY SUFFERED BY LICENSE AS
* A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
***********************************************************************************/
/**
* @example GrabChunks.cpp
*
* @brief "GrabChunks" is an extension of the simple Grab example which introduces
* the chunk data functionality. Along with the image data itself, images can
* be shipped along with additional information. This additional data is arranged in
* "chunks". For instance, an image can contain two chunks: its timestamp and the
* temperature of the device at the moment of the acquisition. Chunks can be read
* as GenICam features returned by the IImage interface.
*
* Suggested examples:
* @see GrabTrigger.cpp
* @see Events.cpp
*/
// Include Itala API
#include "ItalaApi/Itala.h"
// Include the GenICam library
#include "GenICam.h"
#define INDENT "\t"
#define ACQUIRE_COUNT 10
void GrabChunks_Sample() {
std::cout << "***** Grab chunks example started. *****" << std::endl << std::endl;
Itala::ISystem* pSystem = Itala::CreateSystem();
Itala::DeviceInfoList deviceInfos = pSystem->EnumerateDevices(700);
if (deviceInfos.size() == 0) throw GENERIC_EXCEPTION("No devices found. Example canceled.");
if (deviceInfos[0].AccessStatus() != Itala::DeviceAccessStatus::AvailableReadWrite)
throw GENERIC_EXCEPTION("Target device is unaccessible in RW mode. Example canceled.");
Itala::IDevice* pDevice = pSystem->CreateDevice(deviceInfos[0]);
std::cout << "First device found is initialized." << std::endl;
std::cout << "Enabling chunk data.." << std::endl;
// Enable the auto exposure time functionality to cause changes in the exposure
// time value when the scene changes or the camera itself is moved.
GenApi::CEnumerationPtr ptrExposureAuto = pDevice->GetNodeMap().GetNode("ExposureAuto");
if (!IsWritable(ptrExposureAuto))
throw GENERIC_EXCEPTION("Unable to activate auto exposure time mode. Aborting.");
int64_t originalExposureAuto = ptrExposureAuto->GetIntValue();
ptrExposureAuto->FromString("Continuous");
// The chunk data functionality is enabled via the "ChunkModeActive" feature.
GenApi::CBooleanPtr ptrChunkModeActive = pDevice->GetNodeMap().GetNode("ChunkModeActive");
if (!IsWritable(ptrChunkModeActive))
throw GENERIC_EXCEPTION("Unable to activate chunk mode. Aborting.");
bool originalChunkModeActive = ptrChunkModeActive->GetValue();
ptrChunkModeActive->SetValue(true);
// Each chunk data available can be enabled individually. In this case, exposure
// time, pixel format and frame timestamp chunks are activated.
// First select the exposure time chunk via the selector and enable it via the
// "ChunkEnable" feature.
GenApi::CEnumerationPtr ptrChunkSelector = pDevice->GetNodeMap().GetNode("ChunkSelector");
if (!IsReadable(ptrChunkSelector))
throw GENERIC_EXCEPTION("Unable to retrieve chunk selector. Aborting.");
ptrChunkSelector->FromString("ExposureTime");
GenApi::CBooleanPtr ptrChunkEnable = pDevice->GetNodeMap().GetNode("ChunkEnable");
bool originalExposureTimeChunkEnabled = ptrChunkEnable->GetValue();
ptrChunkEnable->SetValue(true);
// Do the same for frame ID chunk.
ptrChunkSelector->FromString("FrameID");
bool originalFrameIDChunkEnabled = ptrChunkEnable->GetValue();
ptrChunkEnable->SetValue(true);
// And again for timestamp chunk.
ptrChunkSelector->FromString("Timestamp");
bool originalTimestampChunkEnabled = ptrChunkEnable->GetValue();
ptrChunkEnable->SetValue(true);
std::cout << std::endl;
pDevice->StartAcquisition();
std::cout << "Acquisition started with chunk functionality enabled." << std::endl;
std::cout << std::endl;
std::vector<Itala::IImage*> images;
for (size_t i = 0; i < ACQUIRE_COUNT; i++) {
Itala::IImage* pImage = pDevice->GetNextImage(1000);
if (pImage->IsIncomplete()) {
// Report some info if the image is partially filled.
std::cout << i << " is a incomplete image." << std::endl;
std::cout << INDENT << "Bytes filled: " << pImage->GetBytesFilled() << "/"
<< pImage->GetPayloadSize() << std::endl;
} else {
std::cout << "Image " << i << " grabbed." << std::endl;
}
// Add the image to the acquired frames list so that image chunks can be
// retrieved and displayed after che grab.
images.push_back(pImage);
// The image IS NOT disposed here since it's needed afterwards to get and
// display the attached chunk data.
}
std::cout << std::endl;
// The chunks embedded in the available images are ready to be read.
for (size_t i = 0; i < images.size(); i++) {
Itala::IImage* pImage = images[i];
std::cout << "Retrieving chunks for image " << i << ".." << std::endl;
// Check if the acquired image has embedded chunk data.
if (pImage->HasChunkData()) {
// Chunk data is exposed as a set GenICam features which names ar
// regulated by the SFNC specification. In general, the names of
// chunk features are defined by prepending the "Chunk" prefix
// (e.g. ChunkExposureTime) to the equivalent standard feature
// (e.g. ExposureTime).
GenApi::CFloatPtr pChunkExposureTime = pImage->GetChunkNode("ChunkExposureTime");
GenApi::CIntegerPtr pChunkFrameId = pImage->GetChunkNode("ChunkFrameID");
GenApi::CIntegerPtr pChunkTimestamp = pImage->GetChunkNode("ChunkTimestamp");
std::cout << INDENT << "ChunkExposureTime: " << pChunkExposureTime->GetValue() << std::endl;
std::cout << INDENT << "ChunkFrameID: " << pChunkFrameId->GetValue() << std::endl;
std::cout << INDENT << "ChunkTimestamp: " << pChunkTimestamp->GetValue() << std::endl;
} else {
std::cout << INDENT << "No chunk data attached." << std::endl;
}
// The image can now be disposed: it's not required anymore.
pImage->Dispose();
pImage = nullptr;
std::cout << std::endl;
}
// The acquisition must be stopped AFTER the acquired images have been used
// (to display chunk data, in this case). If the acquisition was stopped
// prematurely, errors may have occurred when accessing the image data (released
// by the library).
pDevice->StopAcquisition();
// Restore the original features state.
ptrExposureAuto->SetIntValue(originalExposureAuto);
ptrChunkSelector->FromString("ExposureTime");
ptrChunkEnable->SetValue(originalExposureTimeChunkEnabled);
ptrChunkSelector->FromString("FrameID");
ptrChunkEnable->SetValue(originalFrameIDChunkEnabled);
ptrChunkSelector->FromString("Timestamp");
ptrChunkEnable->SetValue(originalTimestampChunkEnabled);
ptrChunkModeActive->SetValue(originalChunkModeActive);
pDevice->Dispose();
pDevice = nullptr;
std::cout << "Device instance disposed." << std::endl;
pSystem->Dispose();
pSystem = nullptr;
std::cout << "System instance disposed." << std::endl;
}
int main(int /*argc*/, char** /*argv*/) {
try {
GrabChunks_Sample();
} catch (GenICam::GenericException& e) {
std::cout << e.what() << std::endl;
}
}