// LineTrigger.c /* @brief: This example shows users how to use IKapC library to grab images with GigEVision camera in line trigger mode. */ #include #include #include #include #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 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 line trigger parameters. */ void SetLineTrigger(); /* @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 line trigger parameters. SetLineTrigger(); // 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().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 line trigger parameters. void SetLineTrigger() { ITKSTATUS res = ITKSTATUS_OK; // Close frame trigger mode. res = ItkDevFromString(g_hCamera, "TriggerSelector", "FrameStart"); CHECK(res); res = ItkDevFromString(g_hCamera, "TriggerMode", "Off"); CHECK(res); // Open line trigger mode. res = ItkDevFromString(g_hCamera, "TriggerSelector", "LineStart"); CHECK(res); res = ItkDevFromString(g_hCamera, "TriggerMode", "On"); CHECK(res); // Select trigger source. res = ItkDevFromString(g_hCamera, "TriggerSource", "Line1"); 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'); }