433 lines
12 KiB
C
Raw Permalink Normal View History

2025-12-10 00:01:32 +08:00
// FrameTrigger.c
/* @brief: This example shows users how to use IKapC library to grab images with GigEVision camera in frame trigger mode. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include "IKapC.h"
// The number of frames requested by buffer.
#define STREAM_BUFFER_COUNT 5
// Camera device handle.
ITKDEVICE g_hCamera = NULL;
// Data stream handle.
ITKSTREAM g_hStream = NULL;
// Image buffer handle.
std::vector <ITKBUFFER> g_vectorBuffer;
// Current frame index.
int g_nCurFrameIndex = 0;
// Buffer data.
char *g_bufferData = NULL;
/* @brief: Determine whether the function is called successfully.
* @param[in] errc: Function return value. */
#define CHECK(errc) if (ITKSTATUS_OK != errc) printErrorAndExit(errc)
/* @brief: Configure camera device. */
void ConfigureCamera();
/* @brief: Create data stream and buffer. */
void CreateStreamAndBuffer();
/* @brief: Configure data stream. */
void ConfigureStream();
/* @brief: Set frame trigger parameters. */
void SetFrameTrigger();
/* @brief: Unregister callback functions. */
void UnRegisterCallback();
/* @brief: This function is registered as a callback function. When data stream starts, the function will be called.
* @param[in] eventType: Event type.
* @param[in] pContext: Input parameter. */
void IKAPC_CC cbStartOfStream(uint32_t eventType, void *pContext);
/* @brief: This function is registered as a callback function. When data stream ends, the function will be called.
* @param[in] eventType: Event type.
* @param[in] pContext: Input parameter. */
void IKAPC_CC cbEndOfStream(uint32_t eventType, void *pContext);
/* @brief: This function is registered as a callback function. When grabbing a frame of image finished, the function will be called.
* @param[in] eventType: Event type.
* @param[in] pContext: Input parameter. */
void IKAPC_CC cbOnEndOfFrame(uint32_t eventType, void *pContext);
/* @brief: This function is registered as a callback function. When grabbing images time out, the function will be called.
* @param[in] eventType: Event type.
* @param[in] pContext: Input parameter. */
void IKAPC_CC cbOnTimeOut(uint32_t eventType, void *pContext);
/* @brief: This function is registered as a callback function. When grabbing frame lost, the function will be called.
* @param[in] eventType: Event type.
* @param[in] pContext: Input parameter. */
void IKAPC_CC cbOnFrameLost(uint32_t eventType, void *pContext);
/* @brief: Print error message and exit the program.
* @param[in] errc: Function return value. */
void printErrorAndExit(ITKSTATUS errc);
/* @brief: Users enter Enter to exit the program. */
void pressEnterToExit();
int main(void)
{
// Return value of IKapC functions.
ITKSTATUS res = ITKSTATUS_OK;
// The number of available devices.
uint32_t numDevices = 0;
// The index of device to be opened.
uint32_t devIndex = 0;
// Initialize IKapC runtime environment.
res = ItkManInitialize();
CHECK(res);
// Configure camera device.
ConfigureCamera();
// Set frame trigger parameters.
SetFrameTrigger();
// Create data stream and buffer.
CreateStreamAndBuffer();
// Configure data stream.
ConfigureStream();
// Start grabbing images.
res = ItkStreamStart(g_hStream, ITKSTREAM_CONTINUOUS);
CHECK(res);
// Wait for grabbing images finished.
getchar();
// Stop grabbing images.
ItkStreamStop(g_hStream);
// Unregister callback functions.
UnRegisterCallback();
// Free data stream and buffers.
for (auto it = g_vectorBuffer.begin(); it != g_vectorBuffer.end(); it++)
{
ItkStreamRemoveBuffer(g_hStream, *it);
ItkBufferFree(*it);
}
std::vector<ITKBUFFER>().swap(g_vectorBuffer);
ItkDevFreeStream(g_hStream);
// Close camera device.
res = ItkDevClose(g_hCamera);
CHECK(res);
if (g_bufferData != NULL)
free(g_bufferData);
// Release IKapC runtime environment.
ItkManTerminate();
pressEnterToExit();
return EXIT_SUCCESS;
}
// Configure camera device.
void ConfigureCamera()
{
ITKSTATUS res = ITKSTATUS_OK;
uint32_t numCameras = 0;
// Enumerate the number of available cameras. Before opening the camera, ItkManGetDeviceCount() function must be called.
res = ItkManGetDeviceCount(&numCameras);
CHECK(res);
// When there is no connected cameras.
if (numCameras == 0)
{
printf("No camera.\n");
ItkManTerminate();
pressEnterToExit();
exit(EXIT_FAILURE);
}
// Open GigEVision camera.
for (uint32_t i = 0; i < numCameras; i++)
{
ITKDEV_INFO di;
// Get camera device information.
res = ItkManGetDeviceInfo(i, &di);
printf("Using camera: serial: %s, name: %s, interface: %s.\n", di.SerialNumber, di.FullName, di.DeviceClass);
// When the device is GigEVision camera and the serial number is proper.
if (strcmp(di.DeviceClass, "GigEVision") == 0 && strcmp(di.SerialNumber, "") != 0)
{
ITKGIGEDEV_INFO gvInfo;
// Open camera.
res = ItkDevOpen(i, ITKDEV_VAL_ACCESS_MODE_EXCLUSIVE, &g_hCamera);
CHECK(res);
// Get GigEVision camera device information.
res = ItkManGetGigEDeviceInfo(i, &gvInfo);
CHECK(res);
}
}
}
// Create data stream and buffer.
void CreateStreamAndBuffer()
{
ITKSTATUS res = ITKSTATUS_OK;
// The number of data stream.
uint32_t streamCount = 0;
// Image width.
int64_t nWidth = 0;
// Image height.
int64_t nHeight = 0;
// Pixel format.
uint32_t nFormat = ITKBUFFER_VAL_FORMAT_MONO8;
// Image size.
int64_t nImageSize = 0;
// Pixel format name.
char pixelFormat[16];
// Pixel format name length.
uint32_t pixelFormatLen = 16;
// Get the number of data stream.
res = ItkDevGetStreamCount(g_hCamera, &streamCount);
CHECK(res);
if (streamCount == 0)
{
fprintf(stderr, "Camera does not have image stream channel.");
ItkManTerminate();
pressEnterToExit();
exit(EXIT_FAILURE);
}
// Get image width.
res = ItkDevGetInt64(g_hCamera, "Width", &nWidth);
CHECK(res);
// Get image height.
res = ItkDevGetInt64(g_hCamera, "Height", &nHeight);
CHECK(res);
// Get pixel format.
res = ItkDevToString(g_hCamera, "PixelFormat", pixelFormat, &pixelFormatLen);
CHECK(res);
if (strcmp(pixelFormat, "Mono8") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_MONO8;
else if (strcmp(pixelFormat, "Mono10") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_MONO10;
else if (strcmp(pixelFormat, "Mono10Packed") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_MONO10PACKED;
else if (strcmp(pixelFormat, "BayerGR8") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_BAYER_GR8;
else if (strcmp(pixelFormat, "BayerRG8") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_BAYER_RG8;
else if (strcmp(pixelFormat, "BayerGB8") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_BAYER_GB8;
else if (strcmp(pixelFormat, "BayerBG8") == 0)
nFormat = ITKBUFFER_VAL_FORMAT_BAYER_BG8;
else
{
fprintf(stderr, "Camera does not support pixel format %s.", pixelFormat);
ItkManTerminate();
pressEnterToExit();
exit(EXIT_FAILURE);
}
// Create image buffer.
ITKBUFFER hBuffer;
res = ItkBufferNew(nWidth, nHeight, nFormat, &hBuffer);
CHECK(res);
g_vectorBuffer.push_back(hBuffer);
// Get buffer size.
res = ItkBufferGetPrm(hBuffer,ITKBUFFER_PRM_SIZE, &nImageSize);
CHECK(res);
// Create buffer data saving.
g_bufferData = (char*)malloc(nImageSize);
if (g_bufferData == NULL)
{
pressEnterToExit();
exit(EXIT_FAILURE);
}
// Allocate data stream source.
res = ItkDevAllocStream(g_hCamera, 0, hBuffer, &g_hStream);
CHECK(res);
// Add buffers to data stream.
for (int i =1 ;i < STREAM_BUFFER_COUNT;i++)
{
res = ItkBufferNew(nWidth, nHeight, nFormat, &hBuffer);
CHECK(res);
res = ItkStreamAddBuffer(g_hStream, hBuffer);
CHECK(res);
g_vectorBuffer.push_back(hBuffer);
}
}
// Configure data stream.
void ConfigureStream()
{
ITKSTATUS res = ITKSTATUS_OK;
// Transfer mode.
uint32_t xferMode = ITKSTREAM_VAL_TRANSFER_MODE_SYNCHRONOUS_WITH_PROTECT;
// Grab mode.
uint32_t startMode = ITKSTREAM_VAL_START_MODE_NON_BLOCK;
// Time out time.
uint32_t timeOut = -1;
// Set grab mode.
res = ItkStreamSetPrm(g_hStream, ITKSTREAM_PRM_START_MODE, &startMode);
CHECK(res);
// Set transfer mode.
res = ItkStreamSetPrm(g_hStream, ITKSTREAM_PRM_TRANSFER_MODE, &xferMode);
CHECK(res);
// Set time out time.
res = ItkStreamSetPrm(g_hStream, ITKSTREAM_PRM_TIME_OUT, &timeOut);
CHECK(res);
// Register callback functions.
res = ItkStreamRegisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_START_OF_STREAM, cbStartOfStream, g_hStream);
CHECK(res);
res = ItkStreamRegisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_STREAM, cbEndOfStream, g_hStream);
CHECK(res);
res = ItkStreamRegisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME, cbOnEndOfFrame, g_hStream);
CHECK(res);
res = ItkStreamRegisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_TIME_OUT, cbOnTimeOut, g_hStream);
CHECK(res);
res = ItkStreamRegisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_FRAME_LOST, cbOnFrameLost, g_hStream);
CHECK(res);
}
// Set frame trigger parameters.
void SetFrameTrigger()
{
ITKSTATUS res = ITKSTATUS_OK;
// Close line trigger mode.
res = ItkDevFromString(g_hCamera, "TriggerSelector", "LineStart");
CHECK(res);
res = ItkDevFromString(g_hCamera, "TriggerMode", "Off");
CHECK(res);
// Open frame trigger mode.
res = ItkDevFromString(g_hCamera, "TriggerSelector", "FrameStart");
CHECK(res);
res = ItkDevFromString(g_hCamera, "TriggerMode", "On");
CHECK(res);
// Select trigger source.
res = ItkDevFromString(g_hCamera, "TriggerSource", "Line3");
CHECK(res);
// Set the number of frames to be captured each time.
res = ItkDevSetInt64(g_hCamera, "TriggerFrameCount", 1);
CHECK(res);
}
// Unregister callback functions.
void UnRegisterCallback()
{
ITKSTATUS res = ITKSTATUS_OK;
res = ItkStreamUnregisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_START_OF_STREAM);
res = ItkStreamUnregisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_STREAM);
res = ItkStreamUnregisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME);
res = ItkStreamUnregisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_TIME_OUT);
res = ItkStreamUnregisterCallback(g_hStream, ITKSTREAM_VAL_EVENT_TYPE_FRAME_LOST);
}
// This function is registered as a callback function. When data stream starts, the function will be called.
void IKAPC_CC cbStartOfStream(uint32_t eventType, void *pContext)
{
printf("On start of stream. \n");
}
// This function is registered as a callback function. When data stream ends, the function will be called.
void IKAPC_CC cbEndOfStream(uint32_t eventType, void *pContext)
{
printf("On end of stream. \n");
}
// This function is registered as a callback function. When grabbing a frame of image finished, the function will be called.
void IKAPC_CC cbOnEndOfFrame(uint32_t eventType, void *pContext)
{
ITKSTATUS res = ITKSTATUS_OK;
unsigned bufferStatus = 0;
int64_t nImageSize = 0;
int nBufferIndex = g_nCurFrameIndex % STREAM_BUFFER_COUNT;
ITKBUFFER hBuffer = g_vectorBuffer[nBufferIndex];
res = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_STATE, &bufferStatus);
CHECK(res);
// When buffer is full or buffer is not full but cannot grab a complete frame of image.
if (bufferStatus == ITKBUFFER_VAL_STATE_FULL || bufferStatus == ITKBUFFER_VAL_STATE_UNCOMPLETED)
{
// Read buffer data.
res = ItkBufferGetPrm(hBuffer,ITKBUFFER_PRM_SIZE, &nImageSize);
CHECK(res);
res = ItkBufferRead(hBuffer, 0, g_bufferData, (uint32_t)nImageSize);
CHECK(res);
}
printf("On end of %d frame.\n", ++g_nCurFrameIndex);
}
// This function is registered as a callback function. When grabbing images time out, the function will be called.
void IKAPC_CC cbOnTimeOut(uint32_t eventType, void *pContext)
{
printf("on time out.\n");
}
// This function is registered as a callback function. When grabbing frame lost, the function will be called.
void IKAPC_CC cbOnFrameLost(uint32_t eventType, void *pContext)
{
printf("on frame lost.\n");
}
// Print error message and exit the program.
void printErrorAndExit(ITKSTATUS errc)
{
fprintf(stderr, "Error Code:%08X\n", errc);
ItkManTerminate();
pressEnterToExit();
exit(EXIT_FAILURE);
}
// Users enter Enter to exit the program.
void pressEnterToExit(void)
{
fprintf(stderr, "\nPress enter to exit.\n");
while (getchar() != '\n');
}