GrabCallback¶
GrabCallback.c¶
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "ItalaApiC/ItalaC.h"
#ifdef _WIN32
#include <windows.h>
#define THREAD_HANDLE HANDLE
#define THREAD_RETURN DWORD WINAPI
#define SLEEP_MS(ms) Sleep(ms)
#else
#include <pthread.h>
#include <unistd.h>
#define THREAD_HANDLE pthread_t
#define THREAD_RETURN void*
#define SLEEP_MS(ms) usleep((ms) * 1000)
#endif
#define INDENT "\t"
// Define a convenient type for the callback function pointer
typedef void (*GrabCallback_t)(H_IMAGE hImage);
// Structure to pass data to the acquisition thread
typedef struct {
H_DEVICE hDevice;
GrabCallback_t callback;
volatile bool* pDone;
} AcquisitionThreadData;
// Error manager helper function
ItalaError ErrorManager(ItalaError e) {
size_t sizeMessage = 255;
char* message = (char*)malloc(sizeof(char) * sizeMessage);
ERR_GetLastErrorMessage(message, &sizeMessage);
printf("\nITALA ERROR (%d):\t%s, %zu char\n", ERR_GetLastErrorCode(), message, sizeMessage);
free(message);
return e;
}
/**
* Grab images in a polling loop (until the "done" flag is true). Then call the callback function
* provided by the user. The "done" flag is passed by reference. Don't forget to handle errors,
* otherwise the thread will terminate. This function is meant to be run in a dedicated thread.
*/
THREAD_RETURN AcquisitionLoop(void* pData) {
AcquisitionThreadData* pThreadData = (AcquisitionThreadData*)pData;
H_IMAGE hImage = NULL;
ItalaError error = ItalaErrorSuccess;
while (!(*pThreadData->pDone)) {
error = DEV_GetNextImage(pThreadData->hDevice, 1000, &hImage);
if (error == ItalaErrorSuccess) {
// Call the user callback with the image
pThreadData->callback(hImage);
}
else if (error == ItalaErrorTimeout) {
printf("%sTimeout occurred!\n", INDENT);
}
else {
printf("%sError getting next image.\n", INDENT);
ErrorManager(error);
break;
}
}
#ifdef _WIN32
return 0;
#else
return NULL;
#endif
}
/**
* The actual user callback, called when an image is available.
*/
void GrabCallback(H_IMAGE hImage) {
ItalaError error = ItalaErrorSuccess;
uint64_t frameID = 0;
// Simulate some image processing
SLEEP_MS(10);
// Get and print the frame ID
error = IMG_GetFrameID(hImage, &frameID);
if (error == ItalaErrorSuccess) {
printf("%sImage with ID:%llu processed.\n", INDENT, (unsigned long long)frameID);
}
else {
printf("%sImage processed (could not get frame ID).\n", INDENT);
}
// Dispose the image when no longer needed
error = IMG_Dispose(hImage);
if (error) return ErrorManager(error);
}
int main(int argc, char** argv) {
printf("***** GrabCallback C example started. *****\n\n");
ItalaError error = ItalaErrorSuccess;
H_DEVICE hDevice = NULL;
size_t devicesInfoSize = 0;
DeviceInfo deviceInfo;
volatile bool done = false;
AcquisitionThreadData threadData;
THREAD_HANDLE grabberThread;
// Initialize the system
error = SYS_Initialize();
if (error) return ErrorManager(error);
// Enumerate devices
error = SYS_EnumerateDevices(700);
if (error) return ErrorManager(error);
error = SYS_GetDeviceCount(&devicesInfoSize);
if (error) return ErrorManager(error);
if (devicesInfoSize == 0) {
printf("No devices found. Example canceled.\n");
return ItalaErrorError;
}
// Get the first device
error = SYS_GetDeviceByIndex(0, &deviceInfo);
if (error) return ErrorManager(error);
// Check if the device is accessible in read-write mode
if (deviceInfo.AccessStatus != AvailableReadWrite) {
printf("Target device is unaccessible in RW mode. Example canceled.\n");
return ItalaErrorError;
}
// Create the device
error = SYS_CreateDevice(deviceInfo, &hDevice);
if (error) return ErrorManager(error);
printf("First device initialized.\n");
// Start acquisition
error = DEV_StartAcquisition(hDevice);
if (error) return ErrorManager(error);
printf("Acquisition started.\n\n");
// Prepare thread data
threadData.hDevice = hDevice;
threadData.callback = GrabCallback;
threadData.pDone = &done;
// Start the acquisition thread. The "done" variable is passed by reference
// to the "AcquisitionLoop" function
#ifdef _WIN32
grabberThread = CreateThread(NULL, 0, AcquisitionLoop, &threadData, 0, NULL);
if (grabberThread == NULL) {
printf("Failed to create acquisition thread.\n");
DEV_StopAcquisition(hDevice);
DEV_Dispose(hDevice);
SYS_Dispose();
return ItalaErrorError;
}
#else
if (pthread_create(&grabberThread, NULL, AcquisitionLoop, &threadData) != 0) {
printf("Failed to create acquisition thread.\n");
DEV_StopAcquisition(hDevice);
DEV_Dispose(hDevice);
SYS_Dispose();
return ItalaErrorError;
}
#endif
// Wait for user input to set the "done" flag to true and stop the acquisition
printf("Press Enter to stop acquisition..\n\n");
getchar();
done = true;
// Wait for the thread to finish
#ifdef _WIN32
WaitForSingleObject(grabberThread, INFINITE);
CloseHandle(grabberThread);
#else
pthread_join(grabberThread, NULL);
#endif
// Stop acquisition
error = DEV_StopAcquisition(hDevice);
if (error) return ErrorManager(error);
printf("\nAcquisition stopped.\n\n");
// Dispose the device
error = DEV_Dispose(hDevice);
hDevice = NULL;
if (error) return ErrorManager(error);
printf("Device instance disposed.\n");
// Dispose the system
error = SYS_Dispose();
if (error) return ErrorManager(error);
printf("System instance disposed.\n");
return 0;
}