Skip to content
⚡ Developer documentation for INFINICAM, the real-time high-speed camera (UC-1.1 / GbE-2)

Creating the SingleImage Project

These are the steps to create a program that captures and decodes one frame of compressed data from a GbE-2, and saves it as a file in the PGM format (Portable Graymap), which can be viewed with standard image viewing software.

  1. Write the source code

    Open the main file (e.g. GbE2_SingleImage.cpp) and replace its contents with the following code.

    #include <stdio.h>
    #include <stdlib.h>
    #include <PUCLIB.h> // Load the PUCLIB header
    int main() {
    printf("Starting INFINICAM GbE-2 SingleImage capture...\n");
    // 1. Initialize the SDK
    PUCRESULT ret = PUC_Initialize();
    if (ret != PUC_SUCCEEDED) {
    printf("Error: Failed to initialize the SDK. ErrorCode: %d\n", ret);
    return EXIT_FAILURE;
    }
    // 2. Search for a GbE-2 device on the network
    PUC_DETECT_FILTER filter = { 0 };
    filter.nDeviceTypeFlags = PUC_DETECT_TARGET_GBE2; // Specify GbE-2
    PUC_DETECT_INFO detectInfo = { 0 };
    ret = PUC_DetectDevice2(&filter, &detectInfo);
    if (ret != PUC_SUCCEEDED || detectInfo.nDeviceCount == 0) {
    printf("Error: No GbE-2 camera was found. ErrorCode: %d\n", ret);
    return EXIT_FAILURE;
    }
    // 3. Open the first detected device
    PUC_HANDLE hDevice = NULL;
    ret = PUC_OpenDevice2(0, &hDevice);
    if (ret != PUC_SUCCEEDED) {
    printf("Error: Failed to open the device. ErrorCode: %d\n", ret);
    return EXIT_FAILURE;
    }
    // 4. Get the resolution
    UINT32 width = 0, height = 0;
    ret = PUC_GetResolution(hDevice, &width, &height);
    if (ret != PUC_SUCCEEDED) {
    printf("Error: Failed to get the resolution. ErrorCode: %d\n", ret);
    PUC_CloseDevice(hDevice);
    return EXIT_FAILURE;
    }
    printf("Resolution: %u x %u pixels\n", width, height);
    // 5. Retrieve the quantization table in bulk (used for decoding)
    unsigned short qVals[PUC_Q_COUNT] = { 0 };
    ret = PUC_GetQuantization2(hDevice, qVals);
    if (ret != PUC_SUCCEEDED) {
    printf("Error: Failed to get the quantization table. ErrorCode: %d\n", ret);
    PUC_CloseDevice(hDevice);
    return EXIT_FAILURE;
    }
    // 6. Get the transfer data size and allocate buffers
    UINT32 xferDataSize = 0;
    ret = PUC_GetXferDataSize(hDevice, &xferDataSize);
    if (ret != PUC_SUCCEEDED) {
    printf("Error: Failed to get the transfer data size. ErrorCode: %d\n", ret);
    PUC_CloseDevice(hDevice);
    return EXIT_FAILURE;
    }
    // Allocate the buffer to store the compressed data
    unsigned char* pCompressedBuffer = (unsigned char*)malloc(xferDataSize);
    // Allocate the buffer to store the decoded data (the row width is aligned to a multiple of 4)
    UINT32 lineBytes = (width + 3) & ~3;
    unsigned long decodedBufferSize = (unsigned long)lineBytes * height;
    unsigned char* pDecodedBuffer = (unsigned char*)malloc(decodedBufferSize);
    if (pCompressedBuffer == NULL || pDecodedBuffer == NULL) {
    printf("Error: Memory allocation failed.\n");
    free(pCompressedBuffer);
    free(pDecodedBuffer);
    PUC_CloseDevice(hDevice);
    return EXIT_FAILURE;
    }
    // 7. Capture one frame of data
    PUC_XFER_DATA_INFO xferDataInfo = { 0 };
    xferDataInfo.pData = pCompressedBuffer;
    xferDataInfo.nDataSize = xferDataSize;
    printf("Capturing one frame...\n");
    ret = PUC_GetSingleXferData(hDevice, &xferDataInfo);
    if (ret == PUC_SUCCEEDED) {
    // 8. Decode the compressed data
    // As part of GbE-2-specific processing, the SDK automatically applies a 180-degree rotation correction
    ret = PUC_DecodeData(pDecodedBuffer, 0, 0, width, height, lineBytes, pCompressedBuffer, qVals);
    if (ret == PUC_SUCCEEDED) {
    // 9. Save the decoded image in PGM (P5) format
    const char* filename = "captured_image.pgm";
    FILE* fp = NULL;
    if (fopen_s(&fp, filename, "wb") == 0 && fp != NULL) {
    // Write the PGM header (P5 / width / height / max gray value 255)
    fprintf(fp, "P5\n%u %u\n255\n", width, height);
    // Write the valid image data one row at a time
    for (UINT32 y = 0; y < height; y++) {
    fwrite(pDecodedBuffer + (y * lineBytes), sizeof(unsigned char), width, fp);
    }
    fclose(fp);
    printf("SUCCESS: Saved the PGM image file (%s)\n", filename);
    } else {
    printf("Error: Failed to save the file.\n");
    }
    } else {
    printf("Error: Failed to decode the image data. ErrorCode: %d\n", ret);
    }
    } else {
    printf("Error: Failed to capture the image data. ErrorCode: %d\n", ret);
    }
    // 10. Free the memory and close the device
    free(pCompressedBuffer);
    free(pDecodedBuffer);
    PUC_CloseDevice(hDevice);
    return EXIT_SUCCESS;
    }
  2. Build and run

    1. Press Ctrl + Shift + B to build the project.
    2. Make sure puclib.dll and related files are placed in the same folder as the executable (.exe).
    3. Run with Ctrl + F5. If captured_image.pgm is generated directly under the project folder, it has succeeded.

The PGM (Portable Graymap) format is a very simple grayscale image format consisting of a text-based header and binary pixel data.

P5
800 600
255
[Binary pixel data (width x height bytes)]
  1. Magic number (P5): Indicates that this is a binary grayscale image.
  2. Image width and height: Specifies the resolution in pixels, e.g. 800 600.
  3. Maximum brightness value (255): Specifies the maximum gray level of each pixel (255 for 8-bit monochrome).
  4. Pixel data: Immediately after the newline, the brightness array (1 pixel = 1 byte) follows as-is.