This website is being translated through machine translation by a third-party service. Basler does not warrant the accuracy, reliability or timeliness of any information translated by this system and will not accept liability for loss or damage incurred as a result. Content that has not yet been translated appears in English. Switch to English version
/* Basler cameras provide "chunk features": The cameras can generate certain information about each image, e.g. frame counters, time stamps, and CRC checksums, which is appended to the image data as data "chunks". This sample illustrates how to enable chunk features, how to grab images, and how to process the appended data. When the camera is in chunk mode, it transfers data blocks that are partitioned into chunks. The first chunk is always the image data. When chunk features are enabled, the image data chunk is followed by chunks containing the information generated by the chunk features. This sample also demonstrates how to use software triggers. Two buffers are used. Once a buffer is filled, the acquisition of the next frame is triggered before processing the received buffer. This approach allows performing image acquisition while the processing of the previous image proceeds.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<pylonc/PylonC.h>#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* Calculates the minimum and maximum gray value. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax);#define NUM_GRABS 20 /* Number of images to grab. */#define NUM_BUFFERS 2 /* Number of buffers used for grabbing. */intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. */PYLON_STREAMGRABBER_HANDLEhGrabber;/* Handle for the pylon stream grabber. */PYLON_CHUNKPARSER_HANDLEhChunkParser;/* Handle for the parser extracting the chunk data. */PYLON_WAITOBJECT_HANDLEhWait;/* Handle used for waiting for a grab to be finished. */size_tpayloadSize;/* Size of an image frame in bytes. */unsignedchar*buffers[NUM_BUFFERS];/* Buffers used for grabbing. */PYLON_STREAMBUFFER_HANDLEbufHandles[NUM_BUFFERS];/* Handles for the buffers. */PylonGrabResult_tgrabResult;/* Stores the result of a grab operation. */intnGrabs;/* Counts the number of buffers grabbed. */size_tnStreams;/* The number of streams the device provides. */_BoolisAvail;/* Used for checking feature availability. */_BoolisReady;/* Used as an output parameter. */size_ti;/* Counter. */intret=EXIT_FAILURE;/* The return value. */constchar*triggerSelectorValue="FrameStart";/* Preselect the trigger for image acquisition. */_BoolisAvailFrameStart;/* Used for checking feature availability. */_BoolisAvailAcquisitionStart;/* Used for checking feature availability. */hDev=PYLONC_INVALID_HANDLE;/* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();printf("Enumerating devices ...\n");/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found.\n");/* Before exiting a program, PylonTerminate() should be called to release all pylon related resources. */PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}printf("Opening first device ...\n");/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for setting parameters and for grabbing images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Set the pixel format to Mono8 if available, where gray values will be output as 8 bit values for each pixel. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono8");CHECK(res);}/* Check the available camera trigger mode(s) to select the appropriate one: acquisition start trigger mode (used by previous cameras; do not confuse with acquisition start command) or frame start trigger mode (equivalent to previous acquisition start trigger mode). */isAvailAcquisitionStart=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_AcquisitionStart");isAvailFrameStart=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameStart");/* Check to see if the camera implements the acquisition start trigger mode only. */if(isAvailAcquisitionStart&&!isAvailFrameStart){/* ... Select the software trigger as the trigger source. */res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","On");CHECK(res);triggerSelectorValue="AcquisitionStart";}else{/* Camera may have the acquisition start trigger mode and the frame start trigger mode implemented. In this case, the acquisition trigger mode must be switched off. */if(isAvailAcquisitionStart){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame burst start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameBurstStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameBurstStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* To trigger each single frame by software or external hardware trigger: Enable the frame start trigger mode. */res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","On");CHECK(res);}/* Note: the trigger selector must be set to the appropriate trigger mode before setting the trigger source or issuing software triggers. Frame start trigger mode for newer cameras, acquisition start trigger mode for previous cameras. */PylonDeviceFeatureFromString(hDev,"TriggerSelector",triggerSelectorValue);/* Enable software triggering. *//* ... Select the software trigger as the trigger source. */res=PylonDeviceFeatureFromString(hDev,"TriggerSource","Software");CHECK(res);/* When using software triggering, the Continuous frame mode should be used. Once acquisition is started, the camera sends one image each time a software trigger is issued. */res=PylonDeviceFeatureFromString(hDev,"AcquisitionMode","Continuous");CHECK(res);/* For GigE cameras, we recommend increasing the packet size for better performance. When the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size to 1500. *//* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */isAvail=PylonDeviceFeatureIsWritable(hDev,"GevSCPSPacketSize");if(isAvail){/* ... The device supports the packet size feature. Set a value. */res=PylonDeviceSetIntegerFeature(hDev,"GevSCPSPacketSize",1500);CHECK(res);}/* Before enabling individual chunks, the chunk mode in general must be activated. */isAvail=PylonDeviceFeatureIsWritable(hDev,"ChunkModeActive");if(!isAvail){fprintf(stderr,"The device doesn't support the chunk mode.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Activate the chunk mode. */res=PylonDeviceSetBooleanFeature(hDev,"ChunkModeActive",1);CHECK(res);/* Enable some individual chunks... *//* ... The frame counter chunk feature. *//* Is the chunk available? */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_ChunkSelector_Framecounter");if(isAvail){/* Select the frame counter chunk feature. */res=PylonDeviceFeatureFromString(hDev,"ChunkSelector","Framecounter");CHECK(res);/* Can the chunk feature be activated? */isAvail=PylonDeviceFeatureIsWritable(hDev,"ChunkEnable");if(isAvail){/* Activate the chunk feature. */res=PylonDeviceSetBooleanFeature(hDev,"ChunkEnable",1);CHECK(res);}}else{/* try setting Standard feature naming convention (SFNC) FrameID name*/isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_ChunkSelector_FrameID");if(isAvail){/* Select the frame id chunk feature. */res=PylonDeviceFeatureFromString(hDev,"ChunkSelector","FrameID");CHECK(res);/* Can the chunk feature be activated? */isAvail=PylonDeviceFeatureIsWritable(hDev,"ChunkEnable");if(isAvail){/* Activate the chunk feature. */res=PylonDeviceSetBooleanFeature(hDev,"ChunkEnable",1);CHECK(res);}}}/* ... The CRC checksum chunk feature. *//* Note: Enabling the CRC chunk feature is not a prerequisite for using chunks. Chunks can also be handled when the CRC feature is disabled. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_ChunkSelector_PayloadCRC16");if(isAvail){/* Select the CRC chunk feature. */res=PylonDeviceFeatureFromString(hDev,"ChunkSelector","PayloadCRC16");CHECK(res);/* Can the chunk feature be activated? */isAvail=PylonDeviceFeatureIsWritable(hDev,"ChunkEnable");if(isAvail){/* Activate the chunk feature. */res=PylonDeviceSetBooleanFeature(hDev,"ChunkEnable",1);CHECK(res);}}/* ... The Timestamp chunk feature. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_ChunkSelector_Timestamp");if(isAvail){/* Select the Timestamp chunk feature. */res=PylonDeviceFeatureFromString(hDev,"ChunkSelector","Timestamp");CHECK(res);/* Can the chunk feature be activated? */isAvail=PylonDeviceFeatureIsWritable(hDev,"ChunkEnable");if(isAvail){/* Activate the chunk feature. */res=PylonDeviceSetBooleanFeature(hDev,"ChunkEnable",1);CHECK(res);}}/* The data block containing the image chunk and the other chunks has a self-descriptive layout. A chunk parser is used to extract the appended chunk data from the grabbed image frame. Create a chunk parser. */res=PylonDeviceCreateChunkParser(hDev,&hChunkParser);CHECK(res);if(hChunkParser==PYLONC_INVALID_HANDLE){/* The transport layer doesn't provide a chunk parser. */fprintf(stderr,"No chunk parser available.\n");gotoexit;}/* Image grabbing is done using a stream grabber. A device may be able to provide different streams. A separate stream grabber must be used for each stream. In this sample, we create a stream grabber for the default stream, i.e., the first stream ( index == 0 ). *//* Get the number of streams supported by the device and the transport layer. */res=PylonDeviceGetNumStreamGrabberChannels(hDev,&nStreams);CHECK(res);if(nStreams<1){fprintf(stderr,"The transport layer doesn't support image streams.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev,0,&hGrabber);CHECK(res);res=PylonStreamGrabberOpen(hGrabber);CHECK(res);/* Get a handle for the stream grabber's wait object. The wait object allows waiting for buffers to be filled with grabbed data. */res=PylonStreamGrabberGetWaitObject(hGrabber,&hWait);CHECK(res);/* Determine the required size of the grab buffer. Since activating chunks will increase the payload size and thus the required buffer size, do this after enabling the chunks. */res=PylonStreamGrabberGetPayloadSize(hDev,hGrabber,&payloadSize);CHECK(res);/* Allocate memory for grabbing. */for(i=0;i<NUM_BUFFERS;++i){buffers[i]=(unsignedchar*)malloc(payloadSize);if(NULL==buffers[i]){fprintf(stderr,"Out of memory.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}}/* We must tell the stream grabber the number and size of the buffers we are using. *//* .. We will not use more than NUM_BUFFERS for grabbing. */res=PylonStreamGrabberSetMaxNumBuffer(hGrabber,NUM_BUFFERS);CHECK(res);/* .. We will not use buffers bigger than payloadSize bytes. */res=PylonStreamGrabberSetMaxBufferSize(hGrabber,payloadSize);CHECK(res);/* Allocate the resources required for grabbing. After this, critical parameters that impact the payload size must not be changed until FinishGrab() is called. */res=PylonStreamGrabberPrepareGrab(hGrabber);CHECK(res);/* Before using the buffers for grabbing, they must be registered at the stream grabber. For each registered buffer, a buffer handle is returned. After registering, these handles are used instead of the raw pointers. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberRegisterBuffer(hGrabber,buffers[i],payloadSize,&bufHandles[i]);CHECK(res);}/* Feed the buffers into the stream grabber's input queue. For each buffer, the API allows passing in a pointer to additional context information. This pointer will be returned unchanged when the grab is finished. In our example, we use the index of the buffer as context information. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberQueueBuffer(hGrabber,bufHandles[i],(void*)i);CHECK(res);}/* Start the image acquisition engine. */res=PylonStreamGrabberStartStreamingIfMandatory(hGrabber);CHECK(res);/* Issue an acquisition start command. Because the trigger mode is enabled, issuing the acquisition start command itself will not trigger any image acquisitions. Issuing the start command simply prepares the camera to acquire images. Once the camera is prepared it will acquire one image for every trigger it receives. */res=PylonDeviceExecuteCommandFeature(hDev,"AcquisitionStart");CHECK(res);/* Trigger the first image. */res=PylonDeviceExecuteCommandFeature(hDev,"TriggerSoftware");CHECK(res);/* Grab NUM_GRABS images */nGrabs=0;/* Counts the number of images grabbed. */while(nGrabs<NUM_GRABS){size_tbufferIndex;/* Index of the buffer. */unsignedcharmin,max;int32_tchunkWidth=0;/* Data retrieved from the chunk parser. */int32_tchunkHeight=0;/* Data retrieved from the chunk parser. *//* Wait for the next buffer to be filled. Wait up to 1000 ms. */res=PylonWaitObjectWait(hWait,1000,&isReady);CHECK(res);if(!isReady){/* Timeout occurred. */fprintf(stderr,"Grab timeout occurred.\n");break;/* Stop grabbing. */}/* Since the wait operation was successful, the result of at least one grab operation is available. Retrieve it. */res=PylonStreamGrabberRetrieveResult(hGrabber,&grabResult,&isReady);CHECK(res);if(!isReady){/* Oops. No grab result available? We should never have reached this point. Since the wait operation above returned without a timeout, a grab result should be available. */fprintf(stderr,"Failed to retrieve a grab result\n");break;}nGrabs++;/* Trigger the next image. Since we passed more than one buffer to the stream grabber, the triggered image will be grabbed while the image processing is performed. */res=PylonDeviceExecuteCommandFeature(hDev,"TriggerSoftware");CHECK(res);/* Get the buffer index from the context information. */bufferIndex=(size_t)grabResult.Context;/* Check to see if the image was grabbed successfully. */if(grabResult.Status==Grabbed){/* The grab is successfull. */unsignedchar*buffer;/* Pointer to the buffer attached to the grab result. *//* Get the buffer pointer from the result structure. Since we also got the buffer index, we could alternatively use buffers[bufferIndex]. */buffer=(unsignedchar*)grabResult.pBuffer;printf("Grabbed frame #%2d into buffer %2d.\n",nGrabs,(int)bufferIndex);/* Check to see if we really got image data plus chunk data. */if(grabResult.PayloadType!=PayloadType_ChunkData){fprintf(stderr,"Received a buffer not containing chunk data?\n");}else{/* Process the chunk data. This is done by passing the grabbed image buffer to the chunk parser. When the chunk parser has processed the buffer, the chunk data can be accessed in the same manner as "normal" camera parameters. The only exception is the CRC feature. There are dedicated functions for checking the CRC checksum. */_BoolhasCRC;/* Let the parser extract the data. */res=PylonChunkParserAttachBuffer(hChunkParser,grabResult.pBuffer,(size_t)grabResult.PayloadSize);CHECK(res);/* Check the CRC. */res=PylonChunkParserHasCRC(hChunkParser,&hasCRC);CHECK(res);if(hasCRC){_BoolisOk;res=PylonChunkParserCheckCRC(hChunkParser,&isOk);CHECK(res);printf("Frame %d contains a CRC checksum. The checksum %s ok.\n",nGrabs,isOk?"is":"is not");}{constchar*featureName="ChunkFramecounter";/* Retrieve the frame counter value. *//* ... Check the availability. */isAvail=PylonDeviceFeatureIsAvailable(hDev,featureName);if(!isAvail){/*if not available try using the SFNC feature FrameID*/featureName="ChunkFrameID";isAvail=PylonDeviceFeatureIsAvailable(hDev,featureName);}printf("Frame %d %s a frame counter chunk.\n",nGrabs,isAvail?"contains":"doesn't contain");if(isAvail){/* ... Get the value. */int64_tcounter;res=PylonDeviceGetIntegerFeature(hDev,featureName,&counter);CHECK(res);#if __STDC_VERSION__ >= 199901L || defined(__GNUC__)printf("Frame counter of frame %d: %lld.\n",nGrabs,(longlong)counter);#elseprintf("Frame counter of frame %d: %I64d.\n",nGrabs,counter);#endif}}/* Retrieve the frame width value. *//* ... Check the availability. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"ChunkWidth");printf("Frame %d %s a width chunk.\n",nGrabs,isAvail?"contains":"doesn't contain");if(isAvail){/* ... Get the value. */res=PylonDeviceGetIntegerFeatureInt32(hDev,"ChunkWidth",&chunkWidth);CHECK(res);printf("Width of frame %d: %d.\n",nGrabs,chunkWidth);}/* Retrieve the frame height value. *//* ... Check the availability. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"ChunkHeight");printf("Frame %d %s a height chunk.\n",nGrabs,isAvail?"contains":"doesn't contain");if(isAvail){/* ... Get the value. */res=PylonDeviceGetIntegerFeatureInt32(hDev,"ChunkHeight",&chunkHeight);CHECK(res);printf("Height of frame %d: %d.\n",nGrabs,chunkHeight);}/* Retrieve the frame timestamp value. *//* ... Check the availability. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"ChunkTimestamp");printf("Frame %d %s a timestamp chunk.\n",nGrabs,isAvail?"contains":"doesn't contain");if(isAvail){/* ... Get the value. */int64_ttimestamp;res=PylonDeviceGetIntegerFeature(hDev,"ChunkTimestamp",×tamp);CHECK(res);#if __STDC_VERSION__ >= 199901L || defined(__GNUC__)printf("Frame timestamp of frame %d: %lld.\n",nGrabs,(longlong)timestamp);#elseprintf("Frame timestamp of frame %d: %I64d.\n",nGrabs,timestamp);#endif}}/* Perform the image processing. */getMinMax(buffer,chunkWidth,chunkHeight,&min,&max);printf("Min. gray value = %3u, Max. gray value = %3u\n",min,max);/* Before requeueing the buffer, you should detach it from the chunk parser. */res=PylonChunkParserDetachBuffer(hChunkParser);/* The chunk data in the buffer is now no longer accessible. */CHECK(res);}elseif(grabResult.Status==Failed){fprintf(stderr,"Frame %d wasn't grabbed successfully. Error code = 0x%08X\n",nGrabs,grabResult.ErrorCode);}/* Once finished with the processing, requeue the buffer to be filled again. */res=PylonStreamGrabberQueueBuffer(hGrabber,grabResult.hBuffer,(void*)bufferIndex);CHECK(res);}/* Clean up. *//* ... Stop the camera. */res=PylonDeviceExecuteCommandFeature(hDev,"AcquisitionStop");CHECK(res);/* ... Stop the image acquisition engine. */res=PylonStreamGrabberStopStreamingIfMandatory(hGrabber);CHECK(res);/* ... We must issue a flush call to ensure that all pending buffers are put into the stream grabber's output queue. */res=PylonStreamGrabberFlushBuffersToOutput(hGrabber);CHECK(res);/* ... The buffers can now be retrieved from the stream grabber. */do{res=PylonStreamGrabberRetrieveResult(hGrabber,&grabResult,&isReady);CHECK(res);}while(isReady);/* ... When all buffers are retrieved from the stream grabber, they can be deregistered. After deregistering the buffers, it is safe to free the memory. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberDeregisterBuffer(hGrabber,bufHandles[i]);CHECK(res);free(buffers[i]);}/* ... Release grabbing related resources. */res=PylonStreamGrabberFinishGrab(hGrabber);CHECK(res);/* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g., the AOI width and height parameters) are unlocked and can be modified again. *//* ... Close the stream grabber. */res=PylonStreamGrabberClose(hGrabber);CHECK(res);/* ... Release the chunk parser. */res=PylonDeviceDestroyChunkParser(hDev,hChunkParser);CHECK(res);ret=EXIT_SUCCESS;exit:/* Disable the software trigger and the chunk mode. */if(hDev!=PYLONC_INVALID_HANDLE){res=PylonDeviceSetBooleanFeature(hDev,"ChunkEnable",0);CHECK(res);res=PylonDeviceSetBooleanFeature(hDev,"ChunkModeActive",0);CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* ... Close and release the pylon device. The stream grabber becomes invalid after closing the pylon device. Don't call stream grabber related methods after closing or releasing the device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);/* ... Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();pressEnterToExit();returnret;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... First find out how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve the more details about the error. ... First find out how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* Simple "image processing" function returning the minimum and maximum gray value of an image with 8 bit gray values. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax){unsignedcharmin=255;unsignedcharmax=0;unsignedcharval;constunsignedchar*p;for(p=pImg;p<pImg+width*height;p++){val=*p;if(val>max)max=val;if(val<min)min=val;}*pMin=min;*pMax=max;}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/*This sample illustrates how to configure the Compression Beyond featureon an ace 2 Pro camera.This allows the camera to send compressed image data to the host computer.The compressed image data can be decompressed on the host side using thePylonImageDecompressor set of functions.Using the image compression feature reduces the amount of data transferred,which in turn can result in increasing the resulting frame rate.When compression is used, the camera sends the compressed image data aschunk data. You can use the PylonImageDecompressorDecompressImage functionto convert the the compressed chunk data into the pixel data.Note: Not all camera models support image compression.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<genapic/GenApiC.h>#include<pylonc/PylonC.h>/* Simple error handling. */#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* Calculating the minimum and maximum gray value of an image buffer. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax);/* Configure the camera to use compression. */GENAPIC_RESULTconfigureCompression(PYLON_DEVICE_HANDLEhDev,doubleratio);intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. */NODEMAP_HANDLEhDeviceNodeMap;/* Handle for nodemap. */NODE_HANDLEhDescNode;/* Handle for the register node. */constintnumGrabs=3;/* Number of images to grab. */size_tpayloadSize=0;/* Size of the compressed image data in bytes. */size_tdecompressedImageSize=0;/* Size of a decompressed image frame in bytes. */size_tdescriptorSize=0;/* Size of the compression descriptor. */unsignedchar*descriptorBuf=NULL;/* Buffer used to store compression descriptor. */unsignedchar*imgBufCompressed=NULL;/* Buffer used to store compressed image data. */unsignedchar*imgBuf=NULL;/* Buffer used to store decompressed image data. */_BoolisAvail;inti;/* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device! */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found!\n");/* Before exiting a program, PylonTerminate() must be called to release all pylon-related resources. */PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* The device must be opened in order to configure parameters and grab images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Check whether the camera supports the compression feature. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"ImageCompressionMode");if(isAvail){PYLON_IMAGE_DECOMPRESSOR_HANDLEhDecompressor=PYLONC_INVALID_HANDLE;doublefps=0.;/* Set the pixel format to Mono8, if available, where gray values will be output as 8-bit values for each pixel. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono8");CHECK(res);}/* Disable acquisition start trigger, if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_AcquisitionStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame burst start trigger, if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameBurstStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameBurstStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame start trigger, if available */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* For GigE cameras, Basler recommends increasing the packet size for better performance. If the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size to 1500. */isAvail=PylonDeviceFeatureIsWritable(hDev,"GevSCPSPacketSize");if(isAvail){/* ... The device supports the packet size feature. Set a value. */res=PylonDeviceSetIntegerFeature(hDev,"GevSCPSPacketSize",1500);CHECK(res);}/* Turn off the compression feature to read the FPS without compression. */res=configureCompression(hDev,0.0);CHECK(res);res=PylonDeviceGetFloatFeature(hDev,"ResultingFrameRate",&fps);CHECK(res);printf("Expected frames per second without compression: %.2f\n",fps);/* Configure the camera for lossless compression using a compression ratio of 75 %. You can adjust this value as required. */res=configureCompression(hDev,75.0);CHECK(res);/* Show the FPS with compression turned on. */res=PylonDeviceGetFloatFeature(hDev,"ResultingFrameRate",&fps);CHECK(res);printf("Expected frames per second using compression: %.2f\n",fps);/* Determine the required size of the grab buffer. */{PYLON_STREAMGRABBER_HANDLEhGrabber;int64_tvalue;/* Temporary create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev,0,&hGrabber);CHECK(res);res=PylonStreamGrabberOpen(hGrabber);CHECK(res);/* With compression turned on, the returned payload size is the estimated maximum size of the compressed image data. The actual size of image data transferred may be smaller, depending on image contents. */res=PylonStreamGrabberGetPayloadSize(hDev,hGrabber,&payloadSize);CHECK(res);res=PylonStreamGrabberClose(hGrabber);CHECK(res);/* Get the size of the decompressed image data. */res=PylonDeviceGetIntegerFeature(hDev,"BslImageCompressionBCBDecompressedImageSize",&value);CHECK(res);decompressedImageSize=(size_t)value;}/* Create the decompressor. */res=PylonImageDecompressorCreate(&hDecompressor);CHECK(res);/* Get size of the compression descriptor required to decompress the image data from a register node. There is no pylon convenience function to read register nodes, so we use genapi functions. */res=PylonDeviceGetNodeMap(hDev,&hDeviceNodeMap);CHECK(res);res=GenApiNodeMapGetNode(hDeviceNodeMap,"BslImageCompressionBCBDescriptor",&hDescNode);CHECK(res);/* Get the length of the register node. */res=GenApiRegisterGetLength(hDescNode,&descriptorSize);CHECK(res);/* Allocate memory for the descriptor. The descriptor is small, allocation should not fail. */descriptorBuf=(unsignedchar*)malloc(descriptorSize);/* Read the compression descriptor from the camera. */res=GenApiRegisterGetValue(hDescNode,descriptorBuf,&descriptorSize);CHECK(res);/* Set the descriptor in the decompressor. */res=PylonImageDecompressorSetCompressionDescriptor(hDecompressor,descriptorBuf,descriptorSize);CHECK(res);/* The decompresser has stored a copy of the descriptor. We can now free the descriptor. */free(descriptorBuf);descriptorBuf=NULL;/* Allocate memory. */imgBufCompressed=(unsignedchar*)malloc(payloadSize);imgBuf=(unsignedchar*)malloc(decompressedImageSize);if(NULL==imgBufCompressed||NULL==imgBuf){fprintf(stderr,"Out of memory.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Grab some images in a loop. */for(i=0;i<numGrabs;++i){PylonGrabResult_tgrabResult={0};PylonCompressionInfo_tcompInfo={0};_BoolbufferReady;/* Grab a single frame from stream channel 0. The camera is set to single frame acquisition mode. Wait up to 2000 ms for the image to be grabbed. */res=PylonDeviceGrabSingleFrame(hDev,0,imgBufCompressed,payloadSize,&grabResult,&bufferReady,2000);if(GENAPI_E_OK==res&&!bufferReady){/* Timeout occurred. */printf("Frame %d: timeout\n",i+1);}CHECK(res);/* Check to see if the data has been received successfully. */if(grabResult.Status==Grabbed&&grabResult.PayloadType==PayloadType_ChunkData){/* Retrieve infos about the compressed image data (sent as chunk data). */res=PylonImageDecompressorGetCompressionInfo(grabResult.pBuffer,(size_t)grabResult.PayloadSize,&compInfo);CHECK(res);/* Does the returned chunk payload contain a successfully compressed image? */if(compInfo.HasCompressedImage&&compInfo.CompressionStatus==CompressionStatus_Ok){unsignedcharmin,max;doubleratio=0;/* Decompress the chunk data into imgBuf. */res=PylonImageDecompressorDecompressImage(hDecompressor,imgBuf,&decompressedImageSize,grabResult.pBuffer,(size_t)grabResult.PayloadSize,NULL);CHECK(res);/* Use the actual size of the returned data. */ratio=(double)grabResult.PayloadSize/(double)compInfo.DecompressedPayloadSize;/* Compressed images are sent as chunk data (PayloadType_ChunkData). Most members of grabResult don't contain valid data. This information can be retrieved from compInfo. *//* Success. Now you can perform image processing on the image. */getMinMax(imgBuf,compInfo.SizeX,compInfo.SizeY,&min,&max);printf("Grabbed frame #%2d: Compression Ratio: %.2f%%, Min. gray value = %3u, Max. gray value = %3u\n",i+1,ratio,min,max);#ifdef GENAPIC_WIN_BUILD/* Display image. */res=PylonImageWindowDisplayImage(0,imgBuf,decompressedImageSize,compInfo.PixelType,compInfo.SizeX,compInfo.SizeY,compInfo.PaddingX,ImageOrientation_TopDown);CHECK(res);#endif}else{printf("Grabbed frame #%2d: Camera could not compress image. CompressionStatus = %d\n",i+1,compInfo.CompressionStatus);}}elseif(grabResult.Status==Failed){fprintf(stderr,"Frame %d wasn't grabbed successfully. Error code = 0x%08X\n",i+1,grabResult.ErrorCode);}}/* Free memory. */free(imgBuf);free(imgBufCompressed);/* Free all resources allocated by the decompressor. */res=PylonImageDecompressorDestroy(hDecompressor);CHECK(res);/* Turn off compression. */res=configureCompression(hDev,0.0);CHECK(res);}else{printf("Camera does not support compression.\n");}/* Clean up. Close and release the pylon device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);pressEnterToExit();/* Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();returnEXIT_SUCCESS;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... Find out first how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve more details about the error. ... Find out first how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* Simple "image processing" function returning the minimum and maximum gray value of an 8-bit gray value image. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax){unsignedcharmin=255;unsignedcharmax=0;unsignedcharval;constunsignedchar*p;for(p=pImg;p<pImg+width*height;p++){val=*p;if(val>max)max=val;if(val<min)min=val;}*pMin=min;*pMax=max;}/* This function configures the camera to use compression. The ratio parameter will set the BslImageCompressionRatio feature on the camera. If you pass a ratio of 0 compression will be turned off. */GENAPIC_RESULTconfigureCompression(PYLON_DEVICE_HANDLEhDev,doubleratio){GENAPIC_RESULTres=GENAPI_E_OK;if(ratio==0){/* Turn compression off. */res=PylonDeviceFeatureFromString(hDev,"ImageCompressionMode","Off");}else{/* Turn the compression feature on. */res=PylonDeviceFeatureFromString(hDev,"ImageCompressionMode","BaslerCompressionBeyond");if(res!=GENAPI_E_OK)returnres;/* We're using lossless compression, so image quality is not affected. */res=PylonDeviceFeatureFromString(hDev,"ImageCompressionRateOption","Lossless");if(res!=GENAPI_E_OK)returnres;/* In this sample we use a compression ratio of 75 %. You can adjust this value depending on your image contents and the required frame-rate. In addition, you can also configure the camera for lossy compression. This is not demonstrated in this sample. For more information, refer to the Basler Product Documentation.*/res=PylonDeviceSetFloatFeature(hDev,"BslImageCompressionRatio",ratio);if(res!=GENAPI_E_OK)returnres;}returnres;}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/*Basler GigE Vision cameras can send event messages. For example, when a sensorexposure has finished, the camera can send an end-of-exposure event to the PC. The eventcan be received by the PC before the image data for the finished exposure has been completelytransferred. This sample illustrates the retrieving and processing of event messages.Receiving events is very similar to grabbing images. An event grabber provides a wait object thatis signalled when an event message is available. When an event message is available, it can beretrieved from the event grabber. In contrast to grabbing images, memory buffers for receivingevents need not be provided by the application. Memory buffers to store event messages are organizedby the event grabber itself.The specific layout of event messages depends on the event type and the camera type. The pylon APIuses GenICam support for parsing event messages. This means that the message layout is described in thecamera's XML description file. A GenApi node map is created from the XML camera description file.This node map contains node objects representing the elements of the XML file. Since the layout of eventmessages is described in the camera description file, the information carried by the event messages isexposed as nodes in the node map and can be accessed like "normal" camera parameters.You can register callback functions that are fired when a parameter has been changed. To beinformed that a received event message contains a specific event, a callback must be registered forthe parameter(s) associated with the event.These mechanisms are demonstrated with the end-of-exposure event. The event carries the followinginformation:* ExposureEndEventFrameID: indicates the number of the image frame that has been exposed.* ExposureEndEventTimestamp: indicates the moment when the event has been generated.* ExposureEndEventStreamChannelIndex: indicates the number of the image data stream used totransfer the exposed frame.A callback for the ExposureEndEventFrameID will be registered as an indicator for the arrivalof an end-of-exposure event.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<pylonc/PylonC.h>#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* Calculates the minimum and maximum gray value. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax);/* The function to be fired when an end of exposure event has been received. */voidGENAPIC_CCendOfExposureCallback(NODE_HANDLEhNode);#define NUM_GRABS 100 /* Number of images to grab. */#define NUM_IMAGE_BUFFERS 5 /* Number of buffers used for grabbing. */#define NUM_EVENT_BUFFERS 20 /* Number of buffers used for grabbing. */intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. */PYLON_STREAMGRABBER_HANDLEhStreamGrabber;/* Handle for the pylon stream grabber. */PYLON_EVENTGRABBER_HANDLEhEventGrabber;/* Handle for the event grabber used for receiving events. */PYLON_EVENTADAPTER_HANDLEhEventAdapter;/* Handle for the event adapter used for dispatching events. */PYLON_WAITOBJECT_HANDLEhWaitStream;/* Handle used for waiting for a grab to be finished. */PYLON_WAITOBJECT_HANDLEhWaitEvent;/* Handle used for waiting for an event message. */PYLON_WAITOBJECTS_HANDLEhWaitObjects;/* Container allowing waiting for multiple wait objects. */NODEMAP_HANDLEhNodeMap;/* Handle for the node map containing the camera parameters. */NODE_CALLBACK_HANDLEhCallback;/* Used for deregistering a callback function. */NODE_HANDLEhNode;/* Handle for a camera parameter. */size_tpayloadSize;/* Size of an image in bytes. */unsignedchar*buffers[NUM_IMAGE_BUFFERS];/* Buffers used for grabbing. */PYLON_STREAMBUFFER_HANDLEbufHandles[NUM_IMAGE_BUFFERS];/* Handles for the buffers. */PylonGrabResult_tgrabResult;/* Stores the result of a grab operation. */intnGrabs;/* Counts the number of buffers grabbed. */size_tnStreams;/* The number of streams the device provides. */_BoolisAvail;/* Used for checking feature availability. */_BoolisReady;/* Used as an output parameter. */size_ti;/* Counter. */int32_tsfncVersionMajor;/* The major number of the Standard Feature Naming Convention (SFNC) version used by the camera device. *//* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for settig parameters, for grabbing images, and for grabbing events. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM|PYLONC_ACCESS_MODE_EVENT);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev,"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev,"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera %s\n",buf);}}/* Set the pixel format to Mono8 if available, where gray values will be output as 8 bit values for each pixel. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono8");CHECK(res);}/* Disable acquisition start trigger if available */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_AcquisitionStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame burst start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameBurstStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameBurstStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame start trigger if available */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* We will use the Continuous frame mode, i.e., the camera delivers images continuously. */res=PylonDeviceFeatureFromString(hDev,"AcquisitionMode","Continuous");CHECK(res);/* For GigE cameras, we recommend increasing the packet size for better performance. If the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size to 1500. *//* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */isAvail=PylonDeviceFeatureIsWritable(hDev,"GevSCPSPacketSize");if(isAvail){/* ... The device supports the packet size feature, set a value. */res=PylonDeviceSetIntegerFeature(hDev,"GevSCPSPacketSize",1500);CHECK(res);}isAvail=PylonDeviceFeatureIsWritable(hDev,"EventSelector");if(!isAvail){/* Feature is not available. */fprintf(stderr,"Device doesn't support events.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Determine the major number of the SFNC version used by the camera device. */if(PylonDeviceGetIntegerFeatureInt32(hDev,"DeviceSFNCVersionMajor",&sfncVersionMajor)!=GENAPI_E_OK){/* No SFNC version information is provided by the camera device. */sfncVersionMajor=0;}/* Enable camera event reporting. *//* Select the end-of-exposure event reporting. */res=PylonDeviceFeatureFromString(hDev,"EventSelector","ExposureEnd");CHECK(res);/* Enable the event reporting. Select the enumeration entry name depending on the SFNC version used by the camera device. */if(sfncVersionMajor>=2)res=PylonDeviceFeatureFromString(hDev,"EventNotification","On");elseres=PylonDeviceFeatureFromString(hDev,"EventNotification","GenICamEvent");CHECK(res);/* Image grabbing is done using a stream grabber. A device may be able to provide different streams. A separate stream grabber must be used for each stream. In this sample, we create a stream grabber for the default stream, i.e., the first stream ( index == 0 ). *//* Get the number of streams supported by the device and the transport layer. */res=PylonDeviceGetNumStreamGrabberChannels(hDev,&nStreams);CHECK(res);if(nStreams<1){fprintf(stderr,"The transport layer doesn't support image streams\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev,0,&hStreamGrabber);CHECK(res);res=PylonStreamGrabberOpen(hStreamGrabber);CHECK(res);/* Get a handle for the stream grabber's wait object. The wait object allows waiting for buffers to be grabbed. */res=PylonStreamGrabberGetWaitObject(hStreamGrabber,&hWaitStream);CHECK(res);res=PylonStreamGrabberGetPayloadSize(hDev,hStreamGrabber,&payloadSize);CHECK(res);/* Allocate memory for grabbing. */for(i=0;i<NUM_IMAGE_BUFFERS;++i){buffers[i]=(unsignedchar*)malloc(payloadSize);if(NULL==buffers[i]){fprintf(stderr,"Out of memory!\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}}/* We must tell the stream grabber the number and size of the buffers we are using. *//* .. We will not use more than NUM_BUFFERS for grabbing. */res=PylonStreamGrabberSetMaxNumBuffer(hStreamGrabber,NUM_IMAGE_BUFFERS);CHECK(res);/* .. We will not use buffers bigger than payloadSize bytes. */res=PylonStreamGrabberSetMaxBufferSize(hStreamGrabber,payloadSize);CHECK(res);/* Allocate the resources required for grabbing. After this, critical parameters that impact the payload size must not be changed until FinishGrab() is called. */res=PylonStreamGrabberPrepareGrab(hStreamGrabber);CHECK(res);/* Before using the buffers for grabbing, they must be registered at the stream grabber. For each registered buffer, a buffer handle is returned. After registering, these handles are used instead of the raw pointers. */for(i=0;i<NUM_IMAGE_BUFFERS;++i){res=PylonStreamGrabberRegisterBuffer(hStreamGrabber,buffers[i],payloadSize,&bufHandles[i]);CHECK(res);}/* Feed the buffers into the stream grabber's input queue. For each buffer, the API allows passing in a pointer to additional context information. This pointer will be returned unchanged when the grab is finished. In our example, we use the index of the buffer as context information. */for(i=0;i<NUM_IMAGE_BUFFERS;++i){res=PylonStreamGrabberQueueBuffer(hStreamGrabber,bufHandles[i],(void*)i);CHECK(res);}/* The stream grabber is now prepared. As soon as the camera starts to acquire images, the image data will be grabbed into the provided buffers. *//* Create and prepare an event grabber. *//* ... Get a handle for the event grabber. */res=PylonDeviceGetEventGrabber(hDev,&hEventGrabber);CHECK(res);if(hEventGrabber==PYLONC_INVALID_HANDLE){/* The transport layer doesn't support event grabbers. */fprintf(stderr,"No event grabber supported.\n");PylonTerminate();pressEnterToExit();returnEXIT_FAILURE;}/* ... Tell the grabber how many buffers to use. */res=PylonEventGrabberSetNumBuffers(hEventGrabber,NUM_EVENT_BUFFERS);CHECK(res);/* ... Open the event grabber. */res=PylonEventGrabberOpen(hEventGrabber);/* The event grabber is now ready for receiving events. */CHECK(res);/* Retrieve the wait object that is associated with the event grabber. The event will be signaled when an event message has been received. */res=PylonEventGrabberGetWaitObject(hEventGrabber,&hWaitEvent);CHECK(res);/* For extracting the event data from an event message, an event adapter is used. */res=PylonDeviceCreateEventAdapter(hDev,&hEventAdapter);CHECK(res);if(hEventAdapter==PYLONC_INVALID_HANDLE){/* The transport layer doesn't support event grabbers. */fprintf(stderr,"No event adapter supported.\n");PylonTerminate();pressEnterToExit();returnEXIT_FAILURE;}/* Register the callback function for ExposureEndEventFrameID parameter. *//*... Get the node map containing all parameters. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Get the ExposureEndEventFrameID parameter. Select the parameter name depending on the SFNC version used by the camera device. */if(sfncVersionMajor>=2)res=GenApiNodeMapGetNode(hNodeMap,"EventExposureEndFrameID",&hNode);elseres=GenApiNodeMapGetNode(hNodeMap,"ExposureEndEventFrameID",&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){/* There is no ExposureEndEventFrameID parameter. */fprintf(stderr,"There is no ExposureEndEventFrameID or EventExposureEndFrameID parameter.\n");PylonTerminate();pressEnterToExit();returnEXIT_FAILURE;}/* ... Register the callback function. */res=GenApiNodeRegisterCallback(hNode,endOfExposureCallback,&hCallback);CHECK(res);/* Put the wait objects into a container. *//* ... Create the container. */res=PylonWaitObjectsCreate(&hWaitObjects);CHECK(res);/* ... Add the wait objects' handles. */res=PylonWaitObjectsAddMany(hWaitObjects,2,hWaitEvent,hWaitStream);CHECK(res);/* Start the image acquisition engine. */res=PylonStreamGrabberStartStreamingIfMandatory(hStreamGrabber);CHECK(res);/* Let the camera acquire images. */res=PylonDeviceExecuteCommandFeature(hDev,"AcquisitionStart");CHECK(res);/* Grab NUM_GRABS images. */nGrabs=0;/* Counts the number of images grabbed. */while(nGrabs<NUM_GRABS){size_tbufferIndex;/* Index of the buffer. */size_twaitObjectIndex;/* Index of the wait object that is signalled.*/unsignedcharmin,max;/* Wait for either an image buffer grabbed or an event received. Wait up to 1000 ms. */res=PylonWaitObjectsWaitForAny(hWaitObjects,1000,&waitObjectIndex,&isReady);CHECK(res);if(!isReady){/* Timeout occurred. */fprintf(stderr,"Timeout. Neither grabbed an image nor received an event.\n");break;/* Stop grabbing. */}if(0==waitObjectIndex){PylonEventResult_teventMsg;/* hWaitEvent has been signalled. At least one event message is available. Retrieve it. */res=PylonEventGrabberRetrieveEvent(hEventGrabber,&eventMsg,&isReady);CHECK(res);if(!isReady){/* Oops. No event message available? We should never have reached this point. Since the wait operation above returned without a timeout, an event message should be available. */fprintf(stderr,"Failed to retrieve an event\n");break;}/* Check to see if the event was successfully received. */if(0==eventMsg.ErrorCode){/* Successfully received an event message. *//* Pass the event message to the event adapter. The event adapter will update the parameters related to events and will fire the callbacks registered to event related parameters. */res=PylonEventAdapterDeliverMessage(hEventAdapter,&eventMsg);CHECK(res);}else{fprintf(stderr,"Error when receiving an event: 0x%08x\n",eventMsg.ErrorCode);}}elseif(1==waitObjectIndex){/* hWaitStream has been signalled. The result of at least one grab operation is available. Retrieve it. */res=PylonStreamGrabberRetrieveResult(hStreamGrabber,&grabResult,&isReady);CHECK(res);if(!isReady){/* Oops. No grab result available? We should never have reached this point. Since the wait operation above returned without a timeout, a grab result should be available. */fprintf(stderr,"Failed to retrieve a grab result\n");break;}nGrabs++;/* Get the buffer index from the context information. */bufferIndex=(size_t)grabResult.Context;/* Check to see if the image was grabbed successfully. */if(grabResult.Status==Grabbed){/* Success. Perform image processing. Since we passed more than one buffer to the stream grabber, the remaining buffers are filled while we do the image processing. The processed buffer won't be touched by the stream grabber until we pass it back to the stream grabber. */unsignedchar*buffer;/* Pointer to the buffer attached to the grab result. *//* Get the buffer pointer from the result structure. Since we also got the buffer index, we could alternatively use buffers[bufferIndex]. */buffer=(unsignedchar*)grabResult.pBuffer;getMinMax(buffer,grabResult.SizeX,grabResult.SizeY,&min,&max);printf("Grabbed frame #%2d into buffer %2d. Min. gray value = %3u, Max. gray value = %3u\n",nGrabs,(int)bufferIndex,min,max);}elseif(grabResult.Status==Failed){fprintf(stderr,"Frame %d wasn't grabbed successfully. Error code = 0x%08X\n",nGrabs,grabResult.ErrorCode);}/* Once finished with the processing, requeue the buffer to be filled again. */res=PylonStreamGrabberQueueBuffer(hStreamGrabber,grabResult.hBuffer,(void*)bufferIndex);CHECK(res);}}/* Clean up. *//* ... Stop the camera. */res=PylonDeviceExecuteCommandFeature(hDev,"AcquisitionStop");CHECK(res);/* ... Stop the image acquisition engine. */res=PylonStreamGrabberStopStreamingIfMandatory(hStreamGrabber);CHECK(res);/* ... Switch-off the events. */res=PylonDeviceFeatureFromString(hDev,"EventSelector","ExposureEnd");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"EventNotification","Off");CHECK(res);/* ... We must issue a flush call to ensure that all pending buffers are put into the stream grabber's output queue. */res=PylonStreamGrabberFlushBuffersToOutput(hStreamGrabber);CHECK(res);/* ... The buffers can now be retrieved from the stream grabber. */do{res=PylonStreamGrabberRetrieveResult(hStreamGrabber,&grabResult,&isReady);CHECK(res);}while(isReady);/* ... When all buffers are retrieved from the stream grabber, they can be deregistered. After deregistering the buffers, it is safe to free the memory. */for(i=0;i<NUM_IMAGE_BUFFERS;++i){res=PylonStreamGrabberDeregisterBuffer(hStreamGrabber,bufHandles[i]);CHECK(res);free(buffers[i]);}/* ... Release grabbing related resources. */res=PylonStreamGrabberFinishGrab(hStreamGrabber);CHECK(res);/* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g., the AOI width and height parameters) are unlocked and can be modified again. *//* ... Close the stream grabber. */res=PylonStreamGrabberClose(hStreamGrabber);CHECK(res);/* ... Deregister the callback. */res=GenApiNodeDeregisterCallback(hNode,hCallback);CHECK(res);/* ... Close the event grabber.*/res=PylonEventGrabberClose(hEventGrabber);CHECK(res);/* ... Release the event adapter. */res=PylonDeviceDestroyEventAdapter(hDev,hEventAdapter);CHECK(res);/* ... Release the wait object container. */res=PylonWaitObjectsDestroy(hWaitObjects);CHECK(res);/* ... Close and release the pylon device. The stream grabber becomes invalid after closing the pylon device. Don't call stream grabber related methods after closing or releasing the device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);/* ... Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();pressEnterToExit();returnEXIT_SUCCESS;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... First find out how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve more details about the error ... First find out how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* Simple "image processing" function returning the minumum and maximum grayvalue of an 8 bit gray value image. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax){unsignedcharmin=255;unsignedcharmax=0;unsignedcharval;constunsignedchar*p;for(p=pImg;p<pImg+width*height;p++){val=*p;if(val>max)max=val;if(val<min)min=val;}*pMin=min;*pMax=max;}/* Callback will be fired when an event message contains an end-of-exposure event. */voidGENAPIC_CCendOfExposureCallback(NODE_HANDLEhNode){int64_tframe;GENAPIC_RESULTres;res=GenApiIntegerGetValue(hNode,&frame);CHECK(res);#if __STDC_VERSION__ >= 199901L || defined(__GNUC__)printf("Got end-of-exposure event. Frame number: %lld\n",(longlong)frame);#elseprintf("Got end-of-exposure event. Frame number: %I64d\n",frame);#endif}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/* This sample illustrates how to access the different camera parameter types. It uses the low-level functions provided by GenApiC instead of those provided by pylonC.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<pylonc/PylonC.h>#define STRING_BUFFER_SIZE 512#define CHECK(errc) if (GENAPI_E_OK != errc) printErrorAndExit(errc)/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This function demonstrates how to retrieve the error message for the last failed function call. */staticvoidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... First find out how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve more details about the error ... First find out how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}staticvoidSetMigrationModeEnable(PYLON_DEVICE_HANDLEhDev){NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;constchar*pFeatureName="MigrationModeEnable";/* The name of the feature. */_Boolvalue,bval;/* The value of the feature. */EGenApiNodeTypenodeType;GENAPIC_RESULTres;/* Get a handle for the device's node map. */res=PylonDeviceGetTLNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node. */res=GenApiNodeMapGetNode(hNodeMap,pFeatureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named %s.\n",pFeatureName);return;}/* We want a boolean feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(BooleanNode!=nodeType){fprintf(stderr,"'%s' is not a boolean feature.",pFeatureName);return;}/* Check to see if the feature is readable. */res=GenApiNodeIsReadable(hNode,&bval);CHECK(res);if(bval){/* Retrieve the current state of the feature. */res=GenApiBooleanGetValue(hNode,&value);CHECK(res);fprintf(stdout,"The '%s' feature is %s.",pFeatureName,value?"on":"off");/* Set a new value. */res=GenApiNodeIsWritable(hNode,&bval);CHECK(res);if(bval){value=1;/* New value to turn feature on. */fprintf(stdout,"Switching the %s feature %s.\n",pFeatureName,value?"on":"off");res=GenApiBooleanSetValue(hNode,value);CHECK(res);}else{fprintf(stderr,"Cannot set value for feature '%s' - node not writable.\n",pFeatureName);}}else{fprintf(stderr,"Cannot read feature '%s' - node not readable.\n",pFeatureName);}}/* This function demonstrates how to check the presence, readability, and writability of a feature. */staticvoiddemonstrateAccessibilityCheck(PYLON_DEVICE_HANDLEhDev){NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;constchar*pFeatureName;_Boolval,val_read,val_write;GENAPIC_RESULTres;/* Get a handle for the device's node map. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Check to see if a feature is implemented at all. The 'Width' feature is likely to be implemented by just about every existing camera. */pFeatureName="Width";res=GenApiNodeMapGetNode(hNodeMap,pFeatureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE!=hNode){/* Node exists, check whether feature is implemented. */res=GenApiNodeIsImplemented(hNode,&val);CHECK(res);}else{/* Node does not exist --> feature is not implemented. */val=0;}printf("The '%s' feature %s implemented\n",pFeatureName,val?"is":"is not");/* This feature most likely does not exist */pFeatureName="Weirdness";res=GenApiNodeMapGetNode(hNodeMap,pFeatureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE!=hNode){/* Node exists, check whether feature is implemented. */res=GenApiNodeIsImplemented(hNode,&val);CHECK(res);}else{/* Node does not exist --> feature is not implemented. */val=0;}printf("The '%s' feature %s implemented\n",pFeatureName,val?"is":"is not");/* Although a feature is implemented by the device, it may not be available with the device in its current state. Check to see if the feature is currently available. The GenApiNodeIsAvailable sets val to 0 if either the feature is not implemented or if the feature is not currently available. */pFeatureName="BinningVertical";res=GenApiNodeMapGetNode(hNodeMap,pFeatureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE!=hNode){/* Node exists, check whether feature is available. */res=GenApiNodeIsAvailable(hNode,&val);CHECK(res);}else{/* Node does not exist --> feature is not implemented, and hence not available. */val=0;}printf("The '%s' feature %s available\n",pFeatureName,val?"is":"is not");/* If a feature is available, it could be read-only, write-only, or both readable and writable. Use the GenApiNodeIsReadable() and the GenApiNodeIsReadable() functions(). It is safe to call these functions for features that are currently not available or not implemented by the device. A feature that is not available or not implemented is neither readable nor writable. The readability and writability of a feature can change depending on the current state of the device. For example, the Width parameter might not be writable when the camera is acquiring images. */pFeatureName="Width";res=GenApiNodeMapGetNode(hNodeMap,pFeatureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE!=hNode){/* Node exists, check whether feature is readable. */res=GenApiNodeIsReadable(hNode,&val_read);CHECK(res);res=GenApiNodeIsReadable(hNode,&val_write);CHECK(res);}else{/* Node does not exist --> feature is neither readable nor witable. */val_read=val_write=0;}printf("The '%s' feature %s readable\n",pFeatureName,val_read?"is":"is not");printf("The '%s' feature %s writable\n",pFeatureName,val_write?"is":"is not");printf("\n");}/* This function demonstrates how to handle integer camera parameters. */staticvoiddemonstrateIntFeature(PYLON_DEVICE_HANDLEhDev){NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;staticconstcharfeatureName[]="Width";/* Name of the feature used in this sample: AOI Width. */int64_tval,min,max,incr;/* Properties of the feature. */GENAPIC_RESULTres;/* Return value. */EGenApiNodeTypenodeType;_Boolbval;/* Get a handle for the device's node map. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node */res=GenApiNodeMapGetNode(hNodeMap,featureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named '%s'\n",featureName);return;}/* We want an integer feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(IntegerNode!=nodeType){fprintf(stderr,"'%s' is not an integer feature\n",featureName);return;}/* Query the current value, the range of allowed values, and the increment of the feature. For some integer features, you are not allowed to set every value within the value range. For example, for some cameras the Width parameter must be a multiple of 2. These constraints are expressed by the increment value. Valid values follow the rule: val >= min && val <= max && val == min + n * inc. */res=GenApiNodeIsReadable(hNode,&bval);CHECK(res);if(bval){res=GenApiIntegerGetMin(hNode,&min);/* Get the minimum value. */CHECK(res);res=GenApiIntegerGetMax(hNode,&max);/* Get the maximum value. */CHECK(res);res=GenApiIntegerGetInc(hNode,&incr);/* Get the increment value. */CHECK(res);res=GenApiIntegerGetValue(hNode,&val);/* Get the current value. */CHECK(res);#if __STDC_VERSION__ >= 199901L || defined(__GNUC__)printf("%s: min= %lld max= %lld incr=%lld Value=%lld\n",featureName,(longlong)min,(longlong)max,(longlong)incr,(longlong)val);#elseprintf("%s: min= %I64d max= %I64d incr=%I64d Value=%I64d\n",featureName,min,max,incr,val);#endifres=GenApiNodeIsWritable(hNode,&bval);CHECK(res);if(bval){/* Set the Width half-way between minimum and maximum. */res=GenApiIntegerSetValue(hNode,min+(max-min)/incr/2*incr);CHECK(res);}elsefprintf(stderr,"Cannot set value for feature '%s' - node not writable\n",featureName);}elsefprintf(stderr,"Cannot read feature '%s' - node not readable\n",featureName);}/* Some features involve floating point parameters. This function illustrates how to set and get floating point parameters. */staticvoiddemonstrateFloatFeature(PYLON_DEVICE_HANDLEhDev){NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;staticconstcharfeatureName[]="Gamma";/* The name of the feature used. */_Boolbval;/* Is the feature available? */doublemin,max,value;/* Value range and current value. */EGenApiNodeTypenodeType;GENAPIC_RESULTres;/* Return value. *//* Get a handle for the device's node map */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node. */res=GenApiNodeMapGetNode(hNodeMap,featureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named '%s'\n",featureName);return;}/* We want a float feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(FloatNode!=nodeType){fprintf(stderr,"'%s' is not an floating-point feature\n",featureName);return;}res=GenApiNodeIsReadable(hNode,&bval);CHECK(res);if(bval){/* Query the value range and the current value. */res=GenApiFloatGetMin(hNode,&min);CHECK(res);res=GenApiFloatGetMax(hNode,&max);CHECK(res);res=GenApiFloatGetValue(hNode,&value);CHECK(res);printf("%s: min = %4.2f, max = %4.2f, value = %4.2f\n",featureName,min,max,value);/* Set a new value. */GenApiNodeIsWritable(hNode,&bval);CHECK(res);if(bval){value=0.5*(min+max);printf("Setting %s to %4.2f\n",featureName,value);res=GenApiFloatSetValue(hNode,value);CHECK(res);}elseprintf("Cannot set value for feature '%s' - node not writable\n",featureName);}elseprintf("Cannot read feature '%s' - node not readable\n",featureName);}/* Some features are boolean features that can be switched on and off. This function illustrates how to access boolean features. */staticvoiddemonstrateBooleanFeature(PYLON_DEVICE_HANDLEhDev){NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;staticconstcharfeatureName[]="GammaEnable";/* The name of the feature. */_Boolvalue,bval;/* The value of the feature. */EGenApiNodeTypenodeType;GENAPIC_RESULTres;/* Return value. *//* Get a handle for the device's node map. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node. */res=GenApiNodeMapGetNode(hNodeMap,featureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named '%s'\n",featureName);return;}/* We want a boolean feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(BooleanNode!=nodeType){fprintf(stderr,"'%s' is not a boolean feature\n",featureName);return;}/* Check to see if the feature is readable. */res=GenApiNodeIsReadable(hNode,&bval);CHECK(res);if(bval){/* Retrieve the current state of the feature. */res=GenApiBooleanGetValue(hNode,&value);CHECK(res);printf("The %s features is %s\n",featureName,value?"on":"off");/* Set a new value. */GenApiNodeIsWritable(hNode,&bval);CHECK(res);if(bval){value=(_Bool)!value;/* New value */printf("Switching the %s feature %s\n",featureName,value?"on":"off");res=GenApiBooleanSetValue(hNode,value);CHECK(res);}elseprintf("Cannot set value for feature '%s' - node not writable\n",featureName);}elseprintf("Cannot read feature '%s' - node not readable\n",featureName);}/* Regardless of the parameter's type, any parameter value can be retrieved as a string. Each parameter can be set by passing in a string correspondingly. This function illustrates how to set and get the Width parameter as string. As demonstrated above, the Width parameter is of the integer type. */staticvoiddemonstrateFromStringToString(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="Width";/* The name of the feature. */NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;EGenApiNodeTypenodeType;_BoolbIsReadable;GENAPIC_RESULTres;/* Return value. *//* Get a handle for the device's node map */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node. */res=GenApiNodeMapGetNode(hNodeMap,featureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named '%s'\n",featureName);return;}/* We want an integer feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(IntegerNode!=nodeType){fprintf(stderr,"'%s' is not an integer feature\n",featureName);return;}/* Check to see if the feature is readable. */res=GenApiNodeIsReadable(hNode,&bIsReadable);CHECK(res);if(bIsReadable){size_tlen;char*buf,fixBuf[32];_BoolbIsWritable;/* Get the value of a feature as a string. Normally, getting the value consists of 3 steps: 1.) Determine the required buffer size. 2.) Allocate the buffer. 3.) Retrieve the value. *//* ... Get the required buffer size. The size is queried by passing a NULL pointer as a pointer to the buffer. */res=GenApiNodeToString(hNode,NULL,&len);CHECK(res);/* ... len is set to the required buffer size (terminating zero included). Allocate the memory and retrieve the string. */buf=(char*)malloc(len);res=GenApiNodeToString(hNode,buf,&len);CHECK(res);printf("%s: %s\n",featureName,buf);free(buf);/* You are not necessarily required to query the buffer size in advance. If the buffer is big enough, passing in a buffer and a pointer to its length will work. When the buffer is too small, an error is returned. *//* Passing in a buffer that is too small. */len=1;res=GenApiNodeToString(hNode,fixBuf,&len);if(res==GENAPI_E_INSUFFICIENT_BUFFER){/* The buffer was too small. The required size is indicated by len. */printf("Buffer is too small for the value of '%s'. The required buffer size is %d\n",featureName,(int)len);}elseCHECK(res);/* Unexpected return value. *//* Passing in a buffer with sufficient size. */len=sizeoffixBuf;res=GenApiNodeToString(hNode,fixBuf,&len);CHECK(res);/* A feature can be set as a string using the GenApiNodeFromString() function. If the content of a string can not be converted to the type of the feature, an error is returned. */GenApiNodeIsWritable(hNode,&bIsWritable);CHECK(res);if(bIsWritable){res=GenApiNodeFromString(hNode,"fourty-two");/* Can not be converted to an integer. */if(res!=GENAPI_E_OK){/* Print out an error message. */size_tl;char*msg;GenApiGetLastErrorMessage(NULL,&l);/* Retrieve buffer size for the error message. */msg=(char*)malloc(l);/* Provide memory. */GenApiGetLastErrorMessage(msg,&l);/* Retrieve the message. */printf("%s\n",msg);free(msg);}}elseprintf("Cannot set value for feature '%s' - node not writable\n",featureName);}elseprintf("Cannot read feature '%s' - node not readable\n",featureName);}/* There are camera features that behave like enumerations. These features can take a value from a fixed set of possible values. One example is the pixel format feature. This function illustrates how to deal with enumeration features.*/staticvoiddemonstrateEnumFeature(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="PixelFormat";NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;EGenApiNodeTypenodeType;_Boolbval;GENAPIC_RESULTres;/* Return value. *//* Get a handle for the device's node map. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node. */res=GenApiNodeMapGetNode(hNodeMap,featureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named '%s'\n",featureName);return;}/* We want an enumeration feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(EnumerationNode!=nodeType){fprintf(stderr,"'%s' is not an enumeration feature\n",featureName);return;}/* Check to see if the feature is readable. */res=GenApiNodeIsReadable(hNode,&bval);CHECK(res);/* The allowed values for an enumeration feature are represented as strings. Use the GenApiNodeFromString() and GenApiNodeToString() methods for setting and getting the value of an enumeration feature. */if(bval){/* Symbolic names of pixel formats. */staticconstcharsymMono8[]="Mono8";staticconstcharsymMono16[]="Mono16";staticconstcharsymYUV422Packed[]="YUV422Packed";size_tlen;/* The length of the string. */charvalue[64];/* The current value of the feature. */_BoolsupportsMono8,supportsYUV422Packed,supportsMono16;NODE_HANDLEhEntry;/* Get the current value of the enumeration feature. */len=sizeofvalue;res=GenApiNodeToString(hNode,value,&len);CHECK(res);printf("PixelFormat: %s\n",value);/* For an enumeration feature, the pylon Viewer's "Feature Documentation" window lists the names of the possible values. Some of the values may not be supported by the device. To check if a certain "SomeValue" value for a "SomeFeature" feature can be set, call the GenApiNodeIsAvailable() on the node of the enum entry. *//* Check to see if the Mono8 pixel format can be set. */res=GenApiEnumerationGetEntryByName(hNode,symMono8,&hEntry);CHECK(res);if(hEntry!=GENAPIC_INVALID_HANDLE){res=GenApiNodeIsAvailable(hEntry,&supportsMono8);CHECK(res);}else{supportsMono8=0;}printf("%s %s a supported value for the PixelFormat feature\n",symMono8,supportsMono8?"is":"is not");/* Check to see if the YUV422Packed pixel format can be set. */res=GenApiEnumerationGetEntryByName(hNode,symYUV422Packed,&hEntry);CHECK(res);if(hEntry!=GENAPIC_INVALID_HANDLE){res=GenApiNodeIsAvailable(hEntry,&supportsYUV422Packed);CHECK(res);}else{supportsYUV422Packed=0;}printf("%s %s a supported value for the PixelFormat feature\n",symYUV422Packed,supportsYUV422Packed?"is":"is not");/* Check to see if the Mono16 pixel format can be set. */res=GenApiEnumerationGetEntryByName(hNode,symMono16,&hEntry);CHECK(res);if(hEntry!=GENAPIC_INVALID_HANDLE){res=GenApiNodeIsAvailable(hEntry,&supportsMono16);CHECK(res);}else{supportsMono16=0;}printf("%s %s a supported value for the PixelFormat feature\n",symMono16,supportsMono16?"is":"is not");/* Before writing a value, we recommend checking if the enumeration feature is currently writable. */res=GenApiNodeIsWritable(hNode,&bval);CHECK(res);if(bval){/* The PixelFormat feature is writable, set it to one of the supported values. */if(supportsMono16){printf("Setting PixelFormat to Mono16\n");res=GenApiNodeFromString(hNode,symMono16);CHECK(res);}elseif(supportsYUV422Packed){printf("Setting PixelFormat to YUV422Packed\n");res=GenApiNodeFromString(hNode,symYUV422Packed);CHECK(res);}elseif(supportsMono8){printf("Setting PixelFormat to Mono8\n");res=GenApiNodeFromString(hNode,symMono8);CHECK(res);}/* Reset the PixelFormat feature to its previous value. */res=GenApiNodeFromString(hNode,value);CHECK(res);}elseprintf("Cannot set value for feature '%s' - node not writable\n",featureName);}elseprintf("Cannot read feature '%s' - node not readable\n",featureName);}/* Enumerate all possible entries for an enumerated feature. For every entry, a selection of properties is displayed. A loop similar to the one shown below may be part of a GUI program that wants to fill the entries of a menu. */staticvoiddemonstrateEnumIteration(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="PixelFormat";NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;EGenApiNodeTypenodeType;_Boolbval;GENAPIC_RESULTres;/* Return value. *//* Get a handle for the device's node map */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the feature node. */res=GenApiNodeMapGetNode(hNodeMap,featureName,&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){fprintf(stderr,"There is no feature named '%s'\n",featureName);return;}/* We want an enumeration feature node. */res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(EnumerationNode!=nodeType){fprintf(stderr,"'%s' is not an enumeration feature\n",featureName);return;}/* Check to see if the feature is readable. */res=GenApiNodeIsReadable(hNode,&bval);CHECK(res);if(bval){size_tmax,i;/* check entries. */res=GenApiEnumerationGetNumEntries(hNode,&max);CHECK(res);/* Write out header. */printf("Allowed values for feature '%s':\n""--------------\n",featureName);/* A loop to visit every enumeration entry node once. */for(i=0;i<max;i++){NODE_HANDLEhEntry;charname[128],displayName[STRING_BUFFER_SIZE],description[STRING_BUFFER_SIZE];size_tsiz;_Boolavail;/* Get handle for enumeration entry node. */res=GenApiEnumerationGetEntryByIndex(hNode,i,&hEntry);CHECK(res);/* Get node name. */siz=sizeofname;res=GenApiNodeGetName(hEntry,name,&siz);CHECK(res);/* Get display name. */siz=sizeofdisplayName;res=GenApiNodeGetDisplayName(hEntry,displayName,&siz);CHECK(res);/* Get description. */siz=sizeofdescription;res=GenApiNodeGetDescription(hEntry,description,&siz);CHECK(res);/* Get availability. */res=GenApiNodeIsAvailable(hEntry,&avail);CHECK(res);/* Write out results. */printf("Node name: %s\n""Display name: %s\n""Description: %s\n""Available: %s\n""--------------\n",name,displayName,description,avail?"yes":"no");}}elseprintf("Cannot read feature '%s' - node not readable\n",featureName);}/* Traverse the feature tree, displaying all categories and all features. */staticvoidhandleCategory(NODE_HANDLEhRoot,char*buf,unsignedintdepth){GENAPIC_RESULTres;size_tbufsiz,siz,numfeat,i;/* Write out node name. */siz=bufsiz=STRING_BUFFER_SIZE-depth*2;res=GenApiNodeGetName(hRoot,buf,&siz);CHECK(res);/* Get the number of feature nodes in this category. */res=GenApiCategoryGetNumFeatures(hRoot,&numfeat);CHECK(res);printf("%s category has %u children\n",buf-depth*2,(unsignedint)numfeat);/* Increase indentation. */*buf++=' ';*buf++=' ';bufsiz-=2;++depth;/* Now loop over all feature nodes. */for(i=0;i<numfeat;++i){NODE_HANDLEhNode;EGenApiNodeTypenodeType;/* Get next feature node and check its type. */res=GenApiCategoryGetFeatureByIndex(hRoot,i,&hNode);CHECK(res);res=GenApiNodeGetType(hNode,&nodeType);CHECK(res);if(Category!=nodeType){/* A regular feature. */EGenApiAccessModeam;constchar*amode;siz=bufsiz;res=GenApiNodeGetName(hNode,buf,&siz);CHECK(res);res=GenApiNodeGetAccessMode(hNode,&am);CHECK(res);switch(am){caseNI:amode="not implemented";break;caseNA:amode="not available";break;caseWO:amode="write only";break;caseRO:amode="read only";break;caseRW:amode="read and write";break;default:amode="undefined";break;}printf("%s feature - access: %s\n",buf-depth*2,amode);}else/* Another category node. */handleCategory(hNode,buf,depth);}}staticvoiddemonstrateCategory(PYLON_DEVICE_HANDLEhDev){NODEMAP_HANDLEhNodeMap;NODE_HANDLEhNode;charbuf[512];GENAPIC_RESULTres;/* Get a handle for the device's node map. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the root node. */res=GenApiNodeMapGetNode(hNodeMap,"Root",&hNode);CHECK(res);handleCategory(hNode,buf,0);}/* There are camera features, such as starting image acquisition, that represent a command. This function that loads the factory settings, illustrates how to execute a command feature. */staticvoiddemonstrateCommandFeature(PYLON_DEVICE_HANDLEhDev){staticconstcharselectorName[]="UserSetSelector";staticconstcharcommandName[]="UserSetLoad";NODEMAP_HANDLEhNodeMap;NODE_HANDLEhCommand,hSelector;EGenApiNodeTypenodeType;_Boolbval;GENAPIC_RESULTres;/* Return value. *//* Get a handle for the device's node map. */res=PylonDeviceGetNodeMap(hDev,&hNodeMap);CHECK(res);/* Look up the command node. */res=GenApiNodeMapGetNode(hNodeMap,commandName,&hCommand);CHECK(res);if(GENAPIC_INVALID_HANDLE==hCommand){fprintf(stderr,"There is no feature named '%s'\n",commandName);return;}/* Look up the selector node. */res=GenApiNodeMapGetNode(hNodeMap,selectorName,&hSelector);CHECK(res);if(GENAPIC_INVALID_HANDLE==hSelector){fprintf(stderr,"There is no feature named '%s'\n",selectorName);return;}/* We want a command feature node. */res=GenApiNodeGetType(hCommand,&nodeType);CHECK(res);if(CommandNode!=nodeType){fprintf(stderr,"'%s' is not a command feature\n",selectorName);return;}/* Before executing the user set load command, the configuration set selector must be set to the default set. *//* Check to see if the selector is writable. */res=GenApiNodeIsWritable(hSelector,&bval);CHECK(res);if(bval){/* Choose the default configuration set (with one of the factory setups chosen). */res=GenApiNodeFromString(hSelector,"Default");CHECK(res);}elseprintf("Cannot set selector '%s' - node not writable\n",selectorName);/* Check to see if the command is writable. */res=GenApiNodeIsWritable(hCommand,&bval);CHECK(res);if(bval){/* Execute the configuration set load command. */printf("Loading the default set.\n");res=GenApiCommandExecute(hCommand);CHECK(res);}elseprintf("Cannot execute command '%s' - node not writable\n",commandName);}intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. *//* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for configuring parameters and for grabbing images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev,"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev,"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera %s\n",buf);}}/* Switch on the MigrationModeEnable feature. */SetMigrationModeEnable(hDev);/* Demonstrate how to check the accessibility of a feature. */demonstrateAccessibilityCheck(hDev);puts("");/* Demonstrate how to handle integer camera parameters. */demonstrateIntFeature(hDev);puts("");/* Demonstrate how to handle floating point camera parameters. */demonstrateFloatFeature(hDev);puts("");/* Demonstrate how to handle boolean camera parameters. */demonstrateBooleanFeature(hDev);puts("");/* Each feature can be read as a string and also set as a string. */demonstrateFromStringToString(hDev);puts("");/* Demonstrate how to handle enumeration camera parameters. */demonstrateEnumFeature(hDev);puts("");/* Demonstrate how to iterate enumeration entries. */demonstrateEnumIteration(hDev);puts("");/* Demonstrate how to execute actions. */demonstrateCommandFeature(hDev);puts("");/* Demonstrate category nodes. */demonstrateCategory(hDev);/* Clean up. Close and release the pylon device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);/* Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();pressEnterToExit();returnEXIT_SUCCESS;}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/* This sample illustrates how to grab images and process images using multiple cameras simultaneously. The sample uses a pool of buffers that are passed to a stream grabber to be filled with image data. Once a buffer is filled and ready for processing, the buffer is retrieved from the stream grabber, processed, and passed back to the stream grabber to be filled again. Buffers retrieved from the stream grabber are not overwritten as long as they are not passed back to the stream grabber.*/#ifndef _WIN32_WINNT# define _WIN32_WINNT 0x0400#endif#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<string.h>#include<pylonc/PylonC.h>#ifdef GENAPIC_LINUX_BUILD#include<sys/timerfd.h>#include<alloca.h>#include<errno.h>#include<unistd.h>#endif/* Limits the amount of cameras used for grabbing. It is important to manage the available bandwidth when grabbing with multiple cameras. This applies, for instance, if two GigE cameras are connected to the same network adapter via a switch. To manage the bandwidth, the GevSCPD interpacket delay parameter and the GevSCFTD transmission delay parameter can be set for each GigE camera device. The "Controlling Packet Transmission Timing with the Interpacket and Frame Transmission Delays on Basler GigE Vision Cameras" Application Note (AW000649xx000) provides more information about this topic. */#define NUM_DEVICES 2#define NUM_BUFFERS 5 /* Number of buffers used for grabbing. */#define GIGE_PACKET_SIZE 1500 /* Size of one Ethernet packet. */#define GIGE_PROTOCOL_OVERHEAD 36 /* Total number of bytes of protocol overhead. */#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* Calculating the minimum and maximum gray value. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax);intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevicesAvail;/* Number of available devices. */_BoolisAvail;/* Used for checking feature availability. */intdeviceIndex;/* Index of device used in following variables. */PYLON_WAITOBJECTS_HANDLEwos;/* Wait objects. */#ifdef GENAPIC_WIN_BUILDHANDLEhTimer;/* Grab timer. */#elseintfdTimer;/* Grab timer. */#endifPYLON_WAITOBJECT_HANDLEwoTimer;/* Timer wait object. *//* These are camera specific variables */PYLON_DEVICE_HANDLEhDev[NUM_DEVICES];/* Handle for the pylon device. */PYLON_STREAMGRABBER_HANDLEhGrabber[NUM_DEVICES];/* Handle for the pylon stream grabber. */unsignedchar*buffers[NUM_DEVICES][NUM_BUFFERS];/* Buffers used for grabbing. */PYLON_STREAMBUFFER_HANDLEbufHandles[NUM_DEVICES][NUM_BUFFERS];/* Handles for the buffers. *//* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevicesAvail);CHECK(res);if(numDevicesAvail<NUM_DEVICES){fprintf(stderr,"Not enough devices found. Found %u devices. At least %i devices needed to run this sample.\n",(unsignedint)numDevicesAvail,NUM_DEVICES);PylonTerminate();pressEnterToExit();exit(EXIT_SUCCESS);}/* Create wait objects (must be done outside of the loop). */res=PylonWaitObjectsCreate(&wos);CHECK(res);/* In this sample, we want to grab for a given amount of time, then stop. */#ifdef GENAPIC_WIN_BUILD/* Create a Windows timer, wrap it in a pylon C wait object, and add it to the wait object set. */hTimer=CreateWaitableTimer(NULL,TRUE,NULL);if(hTimer==NULL){fprintf(stderr,"CreateWaitableTimer() failed.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}res=PylonWaitObjectFromW32(hTimer,0,&woTimer);CHECK(res);#else/* Create a Linux timer, wrap it in a pylon C wait object, and add it to the wait object set. */fdTimer=timerfd_create(CLOCK_MONOTONIC,0);if(fdTimer==-1){fprintf(stderr,"timerfd_create() failed. %s\n",strerror(errno));PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}res=PylonWaitObjectFromFd(fdTimer,&woTimer);CHECK(res);#endifres=PylonWaitObjectsAdd(wos,woTimer,NULL);CHECK(res);/* Open cameras and set parameters. */for(deviceIndex=0;deviceIndex<NUM_DEVICES;++deviceIndex){PylonDeviceInfo_tdi;/* Get a handle for the device. */res=PylonCreateDeviceByIndex(deviceIndex,&hDev[deviceIndex]);CHECK(res);/* Before using the device, it must be opened. Open it for setting parameters and for grabbing images. */res=PylonDeviceOpen(hDev[deviceIndex],PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev[deviceIndex],"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev[deviceIndex],"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera '%s'\n",buf);}}/* Set the pixel format to Mono8, where gray values will be output as 8 bit values for each pixel. *//* ... First check to see if the device supports the Mono8 format. */isAvail=PylonDeviceFeatureIsAvailable(hDev[deviceIndex],"EnumEntry_PixelFormat_Mono8");if(!isAvail){/* Feature is not available. */fprintf(stderr,"Device doesn't support the Mono8 pixel format");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* ... Set the pixel format to Mono8. */res=PylonDeviceFeatureFromString(hDev[deviceIndex],"PixelFormat","Mono8");CHECK(res);/* Disable acquisition start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev[deviceIndex],"EnumEntry_TriggerSelector_AcquisitionStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerMode","Off");CHECK(res);}/* Disable frame burst start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev[deviceIndex],"EnumEntry_TriggerSelector_FrameBurstStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerSelector","FrameBurstStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerMode","Off");CHECK(res);}/* Disable frame start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev[deviceIndex],"EnumEntry_TriggerSelector_FrameStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerMode","Off");CHECK(res);}/* We will use the Continuous frame mode, i.e., the camera delivers images continuously. */res=PylonDeviceFeatureFromString(hDev[deviceIndex],"AcquisitionMode","Continuous");CHECK(res);res=PylonDeviceGetDeviceInfo(hDev[deviceIndex],&di);CHECK(res);if(strcmp(di.DeviceClass,"BaslerGigE")==0){/* For GigE cameras, we recommend increasing the packet size for better performance. When the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size to 1500. Also we set the Inter-Packet and the Frame Transmission delay so the switch can line up packets better. */res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"GevSCPSPacketSize",GIGE_PACKET_SIZE);CHECK(res);res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"GevSCPD",(GIGE_PACKET_SIZE+GIGE_PROTOCOL_OVERHEAD)*(NUM_DEVICES-1));CHECK(res);res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"GevSCFTD",(GIGE_PACKET_SIZE+GIGE_PROTOCOL_OVERHEAD)*deviceIndex);CHECK(res);}}/* Allocate and register buffers for grab. */for(deviceIndex=0;deviceIndex<NUM_DEVICES;++deviceIndex){size_ti;PYLON_WAITOBJECT_HANDLEhWait;size_tpayloadSize;/* Image grabbing is done using a stream grabber. A device may be able to provide different streams. A separate stream grabber must be used for each stream. In this sample, we create a stream grabber for the default stream, i.e., the first stream ( index == 0 ). *//* Get the number of streams supported by the device and the transport layer. */res=PylonDeviceGetNumStreamGrabberChannels(hDev[deviceIndex],&i);CHECK(res);if(i<1){fprintf(stderr,"The transport layer doesn't support image streams.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev[deviceIndex],0,&hGrabber[deviceIndex]);CHECK(res);res=PylonStreamGrabberOpen(hGrabber[deviceIndex]);CHECK(res);/* Get a handle for the stream grabber's wait object. The wait object allows waiting for buffers to be filled with grabbed data. */res=PylonStreamGrabberGetWaitObject(hGrabber[deviceIndex],&hWait);CHECK(res);/* Add the stream grabber's wait object to our wait objects. This is needed to be able to wait until at least one camera has grabbed an image in the grab loop below. */res=PylonWaitObjectsAdd(wos,hWait,NULL);CHECK(res);res=PylonStreamGrabberGetPayloadSize(hDev[deviceIndex],hGrabber[deviceIndex],&payloadSize);CHECK(res);/* Allocate memory for grabbing. */for(i=0;i<NUM_BUFFERS;++i){buffers[deviceIndex][i]=(unsignedchar*)malloc(payloadSize);if(NULL==buffers[deviceIndex][i]){fprintf(stderr,"Out of memory.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}}/* We must tell the stream grabber the number and size of the buffers we are using. *//* .. We will not use more than NUM_BUFFERS for grabbing. */res=PylonStreamGrabberSetMaxNumBuffer(hGrabber[deviceIndex],NUM_BUFFERS);CHECK(res);/* .. We will not use buffers bigger than payloadSize bytes. */res=PylonStreamGrabberSetMaxBufferSize(hGrabber[deviceIndex],payloadSize);CHECK(res);/* Allocate the resources required for grabbing. After this, critical parameters that impact the payload size must not be changed until FinishGrab() is called. */res=PylonStreamGrabberPrepareGrab(hGrabber[deviceIndex]);CHECK(res);/* Before using the buffers for grabbing, they must be registered at the stream grabber. For each registered buffer, a buffer handle is returned. After registering, these handles are used instead of the raw pointers. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberRegisterBuffer(hGrabber[deviceIndex],buffers[deviceIndex][i],payloadSize,&bufHandles[deviceIndex][i]);CHECK(res);}/* Feed the buffers into the stream grabber's input queue. For each buffer, the API allows passing in a pointer to additional context information. This pointer will be returned unchanged when the grab is finished. In our example, we use the index of the buffer as context information. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberQueueBuffer(hGrabber[deviceIndex],bufHandles[deviceIndex][i],(void*)i);CHECK(res);}}/* The stream grabber is now prepared. As soon the camera starts to acquire images, the image data will be grabbed into the provided buffers. */for(deviceIndex=0;deviceIndex<NUM_DEVICES;++deviceIndex){/* Start the image acquisition engine. */res=PylonStreamGrabberStartStreamingIfMandatory(hGrabber[deviceIndex]);/* do not call CHECK() here! Instead exit the loop */if(res!=GENAPI_E_OK){break;}/* Let the camera acquire images. */res=PylonDeviceExecuteCommandFeature(hDev[deviceIndex],"AcquisitionStart");/* do not call CHECK() here! Instead exit the loop */if(res!=GENAPI_E_OK){break;}}/* Only start the grab loop if all cameras have been "started" */if(res==GENAPI_E_OK){unsignedintnGrabs=0;/* Set the timer to 5 s and start it. */#ifdef GENAPIC_WIN_BUILDLARGE_INTEGERintv;intv.QuadPart=-50000000I64;if(!SetWaitableTimer(hTimer,&intv,0,NULL,NULL,FALSE)){fprintf(stderr,"SetWaitableTimer() failed.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}#elsestructitimerspectimer_value;timer_value.it_interval.tv_sec=0;timer_value.it_interval.tv_nsec=0;timer_value.it_value.tv_sec=5;timer_value.it_value.tv_nsec=0;if(timerfd_settime(fdTimer,0,&timer_value,NULL)==-1){fprintf(stderr,"timerfd_settime() failed. %s\n",strerror(errno));PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}#endif/* Grab until the timer expires. */for(;;){_BoolisReady;size_twoidx;unsignedcharmin,max;PylonGrabResult_tgrabResult;/* Wait for the next buffer to be filled. Wait up to 1000 ms. */res=PylonWaitObjectsWaitForAny(wos,1000,&woidx,&isReady);CHECK(res);if(!isReady){/* Timeout occurred. */fputs("Grab timeout occurred.\n",stderr);break;/* Stop grabbing. */}/* If the timer has expired, exit the grab loop */if(woidx==0){fputs("Grabbing completed successfully.\n",stderr);break;/* timer expired */}/* Account for the timer. */--woidx;/* Retrieve the grab result. */res=PylonStreamGrabberRetrieveResult(hGrabber[woidx],&grabResult,&isReady);CHECK(res);if(!isReady){/* Oops. No grab result available? We should never have reached this point. Since the wait operation above returned without a timeout, a grab result should be available. */fprintf(stderr,"Failed to retrieve a grab result\n");break;}/* Check to see if the image was grabbed successfully. */if(grabResult.Status==Grabbed){/* Success. Perform image processing. Since we passed more than one buffer to the stream grabber, the remaining buffers are filled while we do the image processing. The processed buffer won't be touched by the stream grabber until we pass it back to the stream grabber. *//* Pointer to the buffer attached to the grab result Get the buffer pointer from the result structure. Since we also got the buffer index, we could alternatively use buffers[bufferIndex]. */unsignedchar*buffer=(unsignedchar*)grabResult.pBuffer;/* Perform processing. */getMinMax(buffer,grabResult.SizeX,grabResult.SizeY,&min,&max);printf("Grabbed frame #%2u from camera %2u into buffer %2p. Min. val=%3u, Max. val=%3u\n",nGrabs,(unsignedint)woidx,grabResult.Context,min,max);#ifdef GENAPIC_WIN_BUILD/* Display image */res=PylonImageWindowDisplayImageGrabResult(woidx,&grabResult);CHECK(res);#endif}elseif(grabResult.Status==Failed){fprintf(stderr,"Frame %u wasn't grabbed successfully. Error code = 0x%08X\n",nGrabs,grabResult.ErrorCode);}/* Once finished with the processing, requeue the buffer to be filled again. */res=PylonStreamGrabberQueueBuffer(hGrabber[woidx],grabResult.hBuffer,grabResult.Context);CHECK(res);nGrabs++;}}/* Clean up. *//* Stop the image acquisition on the cameras. */for(deviceIndex=0;deviceIndex<NUM_DEVICES;++deviceIndex){/* ... Stop the camera. */res=PylonDeviceExecuteCommandFeature(hDev[deviceIndex],"AcquisitionStop");CHECK(res);/* ... Stop the image acquisition engine. */res=PylonStreamGrabberStopStreamingIfMandatory(hGrabber[deviceIndex]);CHECK(res);}/* Remove all wait objects from waitobjects. */res=PylonWaitObjectsRemoveAll(wos);CHECK(res);res=PylonWaitObjectDestroy(woTimer);CHECK(res);res=PylonWaitObjectsDestroy(wos);CHECK(res);for(deviceIndex=0;deviceIndex<NUM_DEVICES;++deviceIndex){size_ti;_Boolrdy;PylonGrabResult_tgrabResult;/* ... We must issue a flush call to ensure that all pending buffers are put into the stream grabber's output queue. */res=PylonStreamGrabberFlushBuffersToOutput(hGrabber[deviceIndex]);CHECK(res);/* ... The buffers can now be retrieved from the stream grabber. */do{res=PylonStreamGrabberRetrieveResult(hGrabber[deviceIndex],&grabResult,&rdy);CHECK(res);}while(rdy);/* ... When all buffers are retrieved from the stream grabber, they can be deregistered. After deregistering the buffers, it is safe to free the memory. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberDeregisterBuffer(hGrabber[deviceIndex],bufHandles[deviceIndex][i]);CHECK(res);free(buffers[deviceIndex][i]);}/* ... Release grabbing related resources. */res=PylonStreamGrabberFinishGrab(hGrabber[deviceIndex]);CHECK(res);/* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g., the AOI width and height parameters) are unlocked and can be modified again. *//* ... Close the stream grabber. */res=PylonStreamGrabberClose(hGrabber[deviceIndex]);CHECK(res);/* ... Close and release the pylon device. The stream grabber becomes invalid after closing the pylon device. Don't call stream grabber related methods after closing or releasing the device. */res=PylonDeviceClose(hDev[deviceIndex]);CHECK(res);res=PylonDestroyDevice(hDev[deviceIndex]);CHECK(res);}pressEnterToExit();/* ... Shut down the pylon runtime system. Don't call any pylon function after calling PylonTerminate(). */PylonTerminate();#ifdef GENAPIC_LINUX_BUILDclose(fdTimer);#endifreturnEXIT_SUCCESS;}/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... First find out how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)alloca(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* Simple "image processing" function returning the minimum and maximum gray value of an 8 bit gray value image. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax){unsignedcharmin=255;unsignedcharmax=0;unsignedcharval;constunsignedchar*p;for(p=pImg;p<pImg+width*height;p++){val=*p;if(val>max)max=val;if(val<min)min=val;}*pMin=min;*pMax=max;}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/* This sample illustrates how to grab and process images asynchronously, i.e., while the application is processing a buffer, the acquistion of the next buffer is done in parallel. The sample uses a pool of buffers that are passed to a stream grabber to be filled with image data. Once a buffer is filled and ready for processing, the buffer is retrieved from the stream grabber, processed, and passed back to the stream grabber to be filled again. Buffers retrieved from the stream grabber are not overwritten as long as they are not passed back to the stream grabber.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<pylonc/PylonC.h>#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* Calculating the minimum and maximum gray value */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax);#define NUM_GRABS 100 /* Number of images to grab. */#define NUM_BUFFERS 5 /* Number of buffers used for grabbing. */intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. */PYLON_STREAMGRABBER_HANDLEhGrabber;/* Handle for the pylon stream grabber. */PYLON_WAITOBJECT_HANDLEhWait;/* Handle used for waiting for a grab to be finished. */size_tpayloadSize;/* Size of an image frame in bytes. */unsignedchar*buffers[NUM_BUFFERS];/* Buffers used for grabbing. */PYLON_STREAMBUFFER_HANDLEbufHandles[NUM_BUFFERS];/* Handles for the buffers. */PylonGrabResult_tgrabResult;/* Stores the result of a grab operation. */intnGrabs;/* Counts the number of buffers grabbed. */size_tnStreams;/* The number of streams the device provides. */_BoolisAvail;/* Used for checking feature availability. */_BoolisReady;/* Used as an output parameter. */size_ti;/* Counter. *//* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for configuring parameters and for grabbing images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev,"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev,"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera %s\n",buf);}}/* Set the pixel format to Mono8 if available, where gray values will be output as 8 bit values for each pixel. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono8");CHECK(res);}/* Disable acquisition start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_AcquisitionStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame burst start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameBurstStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameBurstStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* We will use the Continuous frame acquisition mode, i.e., the camera delivers images continuously. */res=PylonDeviceFeatureFromString(hDev,"AcquisitionMode","Continuous");CHECK(res);/* For GigE cameras, we recommend increasing the packet size for better performance. When the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size to 1500. *//* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */isAvail=PylonDeviceFeatureIsWritable(hDev,"GevSCPSPacketSize");if(isAvail){/* ... The device supports the packet size feature, set a value. */res=PylonDeviceSetIntegerFeature(hDev,"GevSCPSPacketSize",1500);CHECK(res);}/* Image grabbing is done using a stream grabber. A device may be able to provide different streams. A separate stream grabber must be used for each stream. In this sample, we create a stream grabber for the default stream, i.e., the first stream ( index == 0 ). *//* Get the number of streams supported by the device and the transport layer. */res=PylonDeviceGetNumStreamGrabberChannels(hDev,&nStreams);CHECK(res);if(nStreams<1){fprintf(stderr,"The transport layer doesn't support image streams\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev,0,&hGrabber);CHECK(res);res=PylonStreamGrabberOpen(hGrabber);CHECK(res);/* Get a handle for the stream grabber's wait object. The wait object allows waiting for buffers to be filled with grabbed data. */res=PylonStreamGrabberGetWaitObject(hGrabber,&hWait);CHECK(res);/* Determine the minimum size of the grab buffer. The size is determined by the configuration of the camera and the stream grabber. Be aware that this may change by changing critical parameters after this call.*/res=PylonStreamGrabberGetPayloadSize(hDev,hGrabber,&payloadSize);CHECK(res);/* Allocate memory for grabbing. */for(i=0;i<NUM_BUFFERS;++i){buffers[i]=(unsignedchar*)malloc(payloadSize);if(NULL==buffers[i]){fprintf(stderr,"Out of memory!\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}}/* We must tell the stream grabber the number and size of the buffers we are using. *//* .. We will not use more than NUM_BUFFERS for grabbing. */res=PylonStreamGrabberSetMaxNumBuffer(hGrabber,NUM_BUFFERS);CHECK(res);/* .. We will not use buffers bigger than payloadSize bytes. */res=PylonStreamGrabberSetMaxBufferSize(hGrabber,payloadSize);CHECK(res);/* Allocate the resources required for grabbing. After this, critical parameters that impact the payload size must not be changed until FinishGrab() is called. */res=PylonStreamGrabberPrepareGrab(hGrabber);CHECK(res);/* Before using the buffers for grabbing, they must be registered at the stream grabber. For each registered buffer, a buffer handle is returned. After registering, these handles are used instead of the raw pointers. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberRegisterBuffer(hGrabber,buffers[i],payloadSize,&bufHandles[i]);CHECK(res);}/* Feed the buffers into the stream grabber's input queue. For each buffer, the API allows passing in a pointer to additional context information. This pointer will be returned unchanged when the grab is finished. In our example, we use the index of the buffer as context information. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberQueueBuffer(hGrabber,bufHandles[i],(void*)i);CHECK(res);}/* Now the stream grabber is prepared. As soon as the camera starts to acquire images, the image data will be grabbed into the buffers provided. *//* Start the image acquisition engine. */res=PylonStreamGrabberStartStreamingIfMandatory(hGrabber);CHECK(res);/* Let the camera acquire images. */res=PylonDeviceExecuteCommandFeature(hDev,"AcquisitionStart");CHECK(res);/* Grab NUM_GRABS images */nGrabs=0;/* Counts the number of images grabbed */while(nGrabs<NUM_GRABS){size_tbufferIndex;/* Index of the buffer */unsignedcharmin,max;/* Wait for the next buffer to be filled. Wait up to 1000 ms. */res=PylonWaitObjectWait(hWait,1000,&isReady);CHECK(res);if(!isReady){/* Timeout occurred. */fprintf(stderr,"Grab timeout occurred\n");break;/* Stop grabbing. */}/* Since the wait operation was successful, the result of at least one grab operation is available. Retrieve it. */res=PylonStreamGrabberRetrieveResult(hGrabber,&grabResult,&isReady);CHECK(res);if(!isReady){/* Oops. No grab result available? We should never have reached this point. Since the wait operation above returned without a timeout, a grab result should be available. */fprintf(stderr,"Failed to retrieve a grab result\n");break;}nGrabs++;/* Get the buffer index from the context information. */bufferIndex=(size_t)grabResult.Context;/* Check to see if the image was grabbed successfully. */if(grabResult.Status==Grabbed){/* Success. Perform image processing. Since we passed more than one buffer to the stream grabber, the remaining buffers are filled while we do the image processing. The processed buffer won't be touched by the stream grabber until we pass it back to the stream grabber. */unsignedchar*buffer;/* Pointer to the buffer attached to the grab result. *//* Get the buffer pointer from the result structure. Since we also got the buffer index, we could alternatively use buffers[bufferIndex]. */buffer=(unsignedchar*)grabResult.pBuffer;/* Perform processing. */getMinMax(buffer,grabResult.SizeX,grabResult.SizeY,&min,&max);printf("Grabbed frame %2d into buffer %2d. Min. gray value = %3u, Max. gray value = %3u\n",nGrabs,(int)bufferIndex,min,max);#ifdef GENAPIC_WIN_BUILD/* Display image */res=PylonImageWindowDisplayImageGrabResult(0,&grabResult);CHECK(res);#endif}elseif(grabResult.Status==Failed){fprintf(stderr,"Frame %d wasn't grabbed successfully. Error code = 0x%08X\n",nGrabs,grabResult.ErrorCode);}/* Once finished with the processing, requeue the buffer to be filled again. */res=PylonStreamGrabberQueueBuffer(hGrabber,grabResult.hBuffer,(void*)bufferIndex);CHECK(res);}/* Clean up. *//* ... Stop the camera. */res=PylonDeviceExecuteCommandFeature(hDev,"AcquisitionStop");CHECK(res);/* ... Stop the image acquisition engine. */res=PylonStreamGrabberStopStreamingIfMandatory(hGrabber);CHECK(res);/* ... We must issue a flush call to ensure that all pending buffers are put into the stream grabber's output queue. */res=PylonStreamGrabberFlushBuffersToOutput(hGrabber);CHECK(res);/* ... The buffers can now be retrieved from the stream grabber. */do{res=PylonStreamGrabberRetrieveResult(hGrabber,&grabResult,&isReady);CHECK(res);}while(isReady);/* ... When all buffers have been retrieved from the stream grabber, they can be deregistered. After that, it is safe to free the memory. */for(i=0;i<NUM_BUFFERS;++i){res=PylonStreamGrabberDeregisterBuffer(hGrabber,bufHandles[i]);CHECK(res);free(buffers[i]);}/* ... Release grabbing related resources. */res=PylonStreamGrabberFinishGrab(hGrabber);CHECK(res);/* After calling PylonStreamGrabberFinishGrab(), parameters that impact the payload size (e.g., the AOI width and height parameters) are unlocked and can be modified again. *//* ... Close the stream grabber. */res=PylonStreamGrabberClose(hGrabber);CHECK(res);/* ... Close and release the pylon device. The stream grabber becomes invalid after closing the pylon device. Don't call stream grabber related methods after closing or releasing the device. */res=PylonDeviceClose(hDev);CHECK(res);/* ...The device is no longer used, destroy it. */res=PylonDestroyDevice(hDev);CHECK(res);pressEnterToExit();/* ... Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();returnEXIT_SUCCESS;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... First find out how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve more details about the error. ... First find out how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources */pressEnterToExit();exit(EXIT_FAILURE);}/* Simple "image processing" function returning the minimum and maximum gray value of an 8 bit gray value image. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax){unsignedcharmin=255;unsignedcharmax=0;unsignedcharval;constunsignedchar*p;for(p=pImg;p<pImg+width*height;p++){val=*p;if(val>max)max=val;if(val<min)min=val;}*pMin=min;*pMax=max;}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/* This sample illustrates how to read and write the different camera parameter types.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#ifdef __GNUC__#include<alloca.h>#endif#include<pylonc/PylonC.h>#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);voidprintErrorAndExit(GENAPIC_RESULTerrc);voiddemonstrateAccessibilityCheck(PYLON_DEVICE_HANDLE);voiddemonstrateIntFeature(PYLON_DEVICE_HANDLE);voiddemonstrateInt32Feature(PYLON_DEVICE_HANDLE);voiddemonstrateFloatFeature(PYLON_DEVICE_HANDLE);voiddemonstrateBooleanFeature(PYLON_DEVICE_HANDLE);voiddemonstrateFromStringToString(PYLON_DEVICE_HANDLE);voiddemonstrateEnumFeature(PYLON_DEVICE_HANDLE);voiddemonstrateCommandFeature(PYLON_DEVICE_HANDLE);intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. *//* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for configuring parameters and for grabbing images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev,"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev,"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera %s\n",buf);}}/* Demonstrate how to check the accessibility of a feature. */demonstrateAccessibilityCheck(hDev);puts("");/* Demonstrate how to handle integer camera parameters. */demonstrateIntFeature(hDev);puts("");demonstrateInt32Feature(hDev);puts("");/* Demonstrate how to handle floating point camera parameters. */demonstrateFloatFeature(hDev);puts("");/* Demonstrate how to handle boolean camera parameters. */demonstrateBooleanFeature(hDev);puts("");/* Each feature can be read as a string and also set as a string. */demonstrateFromStringToString(hDev);puts("");/* Demonstrate how to handle enumeration camera parameters. */demonstrateEnumFeature(hDev);puts("");/* Demonstrate how to execute actions. */demonstrateCommandFeature(hDev);/* Clean up. Close and release the pylon device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);/* Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();pressEnterToExit();returnEXIT_SUCCESS;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... First find out how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve the more details about the error ... First find out how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources */pressEnterToExit();exit(EXIT_FAILURE);}/* This function demonstrates how to check the presence, readability, and writability of a feature. */voiddemonstrateAccessibilityCheck(PYLON_DEVICE_HANDLEhDev){_Boolval;/* Output of the check functions *//* Check to see if a feature is implemented at all. */val=PylonDeviceFeatureIsImplemented(hDev,"Width");printf("The 'Width' feature %s implemented\n",val?"is":"isn't");val=PylonDeviceFeatureIsImplemented(hDev,"MyCustomFeature");printf("The 'MyCustomFeature' feature %s implemented\n",val?"is":"isn't");/* Although a feature is implemented by the device, it might not be available with the device in its current state. Check to see if the feature is currently available. The PylonDeviceFeatureIsAvailable sets val to 0 if either the feature is not implemented or if the feature is not currently available. */val=PylonDeviceFeatureIsAvailable(hDev,"BinningVertical");printf("The 'BinningVertical' feature %s available\n",val?"is":"isn't");/* If a feature is available, it could be read-only, write-only, or both readable and writable. Use the PylonDeviceFeatureIsReadable() and the PylonDeviceFeatureIsWritable() functions(). It is safe to call these functions for features that are currently not available or not implemented by the device. A feature that is not available or not implemented is neither readable nor writable. The readability and writability of a feature can change depending on the current state of the device. For example, the Width parameter might not be writable when the camera is acquiring images. */val=PylonDeviceFeatureIsReadable(hDev,"Width");printf("The 'Width' feature %s readable\n",val?"is":"isn't");val=PylonDeviceFeatureIsReadable(hDev,"MyCustomFeature");printf("The 'MyCustomFeature' feature %s readable\n",val?"is":"isn't");val=PylonDeviceFeatureIsWritable(hDev,"Width");printf("The 'Width' feature %s writable\n",val?"is":"isn't");printf("\n");}/* This function demonstrates how to handle integer camera parameters. */voiddemonstrateIntFeature(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="Width";/* Name of the feature used in this sample: AOI Width */int64_tval,min,max,incr;/* Properties of the feature */GENAPIC_RESULTres;/* Return value */if(PylonDeviceFeatureIsReadable(hDev,featureName)){/* Query the current value, the allowed value range, and the increment of the feature. For some integer features, you are not allowed to set every value within the value range. For example, for some cameras the Width parameter must be a multiple of 2. These constraints are expressed by the increment value. Valid values follow the rule: val >= min && val <= max && val == min + n * inc. */res=PylonDeviceGetIntegerFeatureMin(hDev,featureName,&min);/* Get the minimum value. */CHECK(res);res=PylonDeviceGetIntegerFeatureMax(hDev,featureName,&max);/* Get the maximum value. */CHECK(res);res=PylonDeviceGetIntegerFeatureInc(hDev,featureName,&incr);/* Get the increment value. */CHECK(res);res=PylonDeviceGetIntegerFeature(hDev,featureName,&val);/* Get the current value. */CHECK(res);#if __STDC_VERSION__ >= 199901L || defined(__GNUC__)printf("%s: min= %lld max= %lld incr=%lld Value=%lld\n",featureName,(longlong)min,(longlong)max,(longlong)incr,(longlong)val);#elseprintf("%s: min= %I64d max= %I64d incr=%I64d Value=%I64d\n",featureName,min,max,incr,val);#endifif(PylonDeviceFeatureIsWritable(hDev,featureName)){/* Set the Width half-way between minimum and maximum. */res=PylonDeviceSetIntegerFeature(hDev,featureName,min+(max-min)/incr/2*incr);CHECK(res);}elsefprintf(stderr,"The %s feature is not writable.\n",featureName);}elsefprintf(stderr,"The %s feature is not readable.\n",featureName);}/* The integer functions illustrated above take 64 bit integers as output parameters. There are variants of the integer functions that accept 32 bit integers instead. The Get.... functions return an error when the value returned by the device doesn't fit into a 32 bit integer. */voiddemonstrateInt32Feature(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="Height";/* Name of the feature used in this sample: AOI height */int32_tval,min,max,incr;/* Properties of the feature */GENAPIC_RESULTres;/* Return value */if(PylonDeviceFeatureIsReadable(hDev,featureName)){/* Query the current value, the allowed value range, and the increment of the feature. For some integer features, you are not allowed to set every value within the value range. For example, for some cameras the Width parameter must be a multiple of 2. These constraints are expressed by the increment value. Valid values follow the rule: val >= min && val <= max && val == min + n * inc. */res=PylonDeviceGetIntegerFeatureMinInt32(hDev,featureName,&min);/* Get the minimum value. */CHECK(res);res=PylonDeviceGetIntegerFeatureMaxInt32(hDev,featureName,&max);/* Get the maximum value. */CHECK(res);res=PylonDeviceGetIntegerFeatureIncInt32(hDev,featureName,&incr);/* Get the increment value. */CHECK(res);res=PylonDeviceGetIntegerFeatureInt32(hDev,featureName,&val);/* Get the current value. */CHECK(res);printf("%s: min= %d max= %d incr=%d Value=%d\n",featureName,min,max,incr,val);if(PylonDeviceFeatureIsWritable(hDev,featureName)){/* Set the value to half its maximum */res=PylonDeviceSetIntegerFeatureInt32(hDev,featureName,min+(max-min)/incr/2*incr);CHECK(res);}elsefprintf(stderr,"The %s feature is not writable.\n",featureName);}elsefprintf(stderr,"The %s feature is not readable.\n",featureName);}/* Some features are floating point features. This function illustrates how to set and get floating point parameters. */voiddemonstrateFloatFeature(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="Gamma";/* The name of the feature used */_BoolisWritable;/* Is the feature writable? */doublemin,max,value;/* Value range and current value */GENAPIC_RESULTres;/* Return value */if(PylonDeviceFeatureIsReadable(hDev,featureName)){/* Query the value range and the current value. */res=PylonDeviceGetFloatFeatureMin(hDev,featureName,&min);CHECK(res);res=PylonDeviceGetFloatFeatureMax(hDev,featureName,&max);CHECK(res);res=PylonDeviceGetFloatFeature(hDev,featureName,&value);CHECK(res);printf("%s: min = %4.2f, max = %4.2f, value = %4.2f\n",featureName,min,max,value);/* Set the value to half its maximum. */isWritable=PylonDeviceFeatureIsWritable(hDev,featureName);if(isWritable){value=0.5*(min+max);printf("Setting %s to %4.2f\n",featureName,value);res=PylonDeviceSetFloatFeature(hDev,featureName,value);CHECK(res);}elsefprintf(stderr,"The %s feature is not writable.\n",featureName);}elsefprintf(stderr,"The %s feature is not readable.\n",featureName);}/* Some features are boolean features that can be switched on and off. This function illustrates how to access boolean features. */voiddemonstrateBooleanFeature(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="GammaEnable";/* The name of the feature */_BoolisWritable;/* Is the feature writable? */_Boolvalue;/* The value of the feature */GENAPIC_RESULTres;/* Return value *//* Check to see if the feature is writable. */isWritable=PylonDeviceFeatureIsWritable(hDev,featureName);if(isWritable){/* Retrieve the current state of the feature. */res=PylonDeviceGetBooleanFeature(hDev,featureName,&value);CHECK(res);printf("The %s features is %s\n",featureName,value?"on":"off");/* Set a new value. */value=(_Bool)!value;/* New value */printf("Switching the %s feature %s\n",featureName,value?"on":"off");res=PylonDeviceSetBooleanFeature(hDev,featureName,value);CHECK(res);}elseprintf("The %s feature isn't writable\n",featureName);}/* Regardless of the parameter's type, any parameter value can be retrieved as a string. Each parameter can be set by passing in a string correspondingly. This function illustrates how to set and get the Width parameter as string. As demonstrated above, the Width parameter is of the integer type. */voiddemonstrateFromStringToString(PYLON_DEVICE_HANDLEhDev){staticconstcharfeatureName[]="Width";/* The name of the feature */size_tlen;char*buf;charsmallBuf[1];charproperBuf[32];GENAPIC_RESULTres;/* Return value *//* Get the value of a feature as a string. Normally getting the value consits of 3 steps: 1.) Determine the required buffer size. 2.) Allocate the buffer. 3.) Retrieve the value. *//* ... Get the required buffer size. The size is queried by passing a NULL pointer as a pointer to the buffer. */res=PylonDeviceFeatureToString(hDev,featureName,NULL,&len);CHECK(res);/* ... Len is set to the required buffer size (terminating zero included). Allocate the memory and retrieve the string. */buf=(char*)alloca(len);res=PylonDeviceFeatureToString(hDev,featureName,buf,&len);CHECK(res);printf("%s: %s\n",featureName,buf);/* You are not necessarily required to query the buffer size in advance. If the buffer is big enough, passing in a buffer and a pointer to its length will work. When the buffer is too small, an error is returned. *//* Passing in a buffer that is too small */len=sizeof(smallBuf);res=PylonDeviceFeatureToString(hDev,featureName,smallBuf,&len);if(res==GENAPI_E_INSUFFICIENT_BUFFER){/* The buffer was too small. The required size is indicated by len. */printf("Buffer is too small for the value of '%s'. The required buffer size is %d\n",featureName,(int)len);}elseCHECK(res);/* Unexpected return value *//* Passing in a buffer with sufficient size. */len=sizeof(properBuf);res=PylonDeviceFeatureToString(hDev,featureName,properBuf,&len);CHECK(res);/* A feature can be set as a string using the PylonDeviceFeatureFromString() function. If the content of a string can not be converted to the type of the feature, an error is returned. */res=PylonDeviceFeatureFromString(hDev,featureName,"fourty-two");/* Can not be converted to an integer */if(res!=GENAPI_E_OK){/* Print out an error message. */size_tl;char*msg;GenApiGetLastErrorMessage(NULL,&l);/* Retrieve buffer size for the error message */msg=(char*)malloc(l);/* Provide memory */GenApiGetLastErrorMessage(msg,&l);/* Retrieve the message */printf("%s\n",msg);free(msg);}}/* There are camera features that behave like enumerations. These features can take a value from a fixed set of possible values. One example is the pixel format feature. This function illustrates how to deal with enumeration features.*/voiddemonstrateEnumFeature(PYLON_DEVICE_HANDLEhDev){charvalue[64];/* The current value of the feature */size_tlen;/* The length of the string */GENAPIC_RESULTres;/* Return value */_BoolisWritable;_BoolsupportsMono8;_BoolsupportsYUV422Packed;_BoolsupportsMono16;/* The allowed values for an enumeration feature are represented as strings. Use thePylonDeviceFeatureFromString() and PylonDeviceFeatureToString() methods for setting and gettingthe value of an enumeration feature. *//* Get the current value of the enumeration feature. */len=sizeof(value);res=PylonDeviceFeatureToString(hDev,"PixelFormat",value,&len);CHECK(res);printf("PixelFormat: %s\n",value);/* For an enumeration feature, the pylon Viewer's "Feature Documentation" window lists the the names of the possible values. Some of the values might not be supported by the device. To check if a certain "SomeValue" value for a "SomeFeature" feature can be set, call the PylonDeviceFeatureIsAvailable() function with "EnumEntry_SomeFeature_SomeValue" as an argument. *//* Check to see if the Mono8 pixel format can be set. */supportsMono8=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8");printf("Mono8 %s a supported value for the PixelFormat feature\n",supportsMono8?"is":"isn't");/* Check to see if the YUV422Packed pixel format can be set. */supportsYUV422Packed=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_YUV422Packed");printf("YUV422Packed %s a supported value for the PixelFormat feature\n",supportsYUV422Packed?"is":"isn't");/* Check to see if the Mono16 pixel format can be set. */supportsMono16=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono16");printf("Mono16 %s a supported value for the PixelFormat feature\n",supportsMono16?"is":"isn't");/* Before writing a value, we recommend checking to see if the enumeration feature is currently writable. */isWritable=PylonDeviceFeatureIsWritable(hDev,"PixelFormat");if(isWritable){/* The PixelFormat feature is writable, set it to one of the supported values. */if(supportsMono16){printf("Setting PixelFormat to Mono16\n");res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono16");CHECK(res);}elseif(supportsYUV422Packed){printf("Setting PixelFormat to YUV422Packed\n");res=PylonDeviceFeatureFromString(hDev,"PixelFormat","YUV422Packed");CHECK(res);}elseif(supportsMono8){printf("Setting PixelFormat to Mono8\n");res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono8");CHECK(res);}/* Reset the PixelFormat feature to its previous value. */PylonDeviceFeatureFromString(hDev,"PixelFormat",value);}}/* There are camera features, such as starting image acquisition, that represent a command. This function that loads the factory settings, illustrates how to execute a command feature. */voiddemonstrateCommandFeature(PYLON_DEVICE_HANDLEhDev){GENAPIC_RESULTres;/* Return value. *//* Before executing the user set load command, the user set selector must be set to the default set. Since we are focusing on the command feature, we skip the recommended steps for checking the availability of the user set related features and values. *//* Choose the default configuration set (with one of the factory setups chosen). */res=PylonDeviceFeatureFromString(hDev,"UserSetSelector","Default");CHECK(res);/* Execute the user set load command. */printf("Loading the default set.\n");res=PylonDeviceExecuteCommandFeature(hDev,"UserSetLoad");CHECK(res);}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/*This sample illustrates how to use the PylonDeviceGrabSingleFrame() conveniencemethod for grabbing images in a loop. PylonDeviceGrabSingleFrame() grabs onesingle frame in single frame mode.Grabbing in single frame acquisition mode is the easiest way to grab images. Note: in single framemode the maximum frame rate of the camera can't be achieved. The full framerate can be achieved by setting the camera to the continuous frame acquisitionmode and by grabbing in overlapped mode, i.e., image acquisition is done in parallelwith image processing. This is illustrated in the OverlappedGrab sample program.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<pylonc/PylonC.h>/* Simple error handling. */#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* Calculating the minimum and maximum gray value of an image buffer */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax);intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. */constintnumGrabs=10;/* Number of images to grab. */size_tpayloadSize=0;/* Size of an image frame in bytes. */unsignedchar*imgBuf;/* Buffer used for grabbing. */_BoolisAvail;inti;/* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device! */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found!\n");/* Before exiting a program, PylonTerminate() should be called to release all pylon related resources. */PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for configuring parameters and for grabbing images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev,"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev,"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera %s\n",buf);}}/* Set the pixel format to Mono8 if available, where gray values will be output as 8 bit values for each pixel. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_PixelFormat_Mono8");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"PixelFormat","Mono8");CHECK(res);}/* Disable acquisition start trigger if available */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_AcquisitionStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","AcquisitionStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame burst start trigger if available. */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameBurstStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameBurstStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* Disable frame start trigger if available */isAvail=PylonDeviceFeatureIsAvailable(hDev,"EnumEntry_TriggerSelector_FrameStart");if(isAvail){res=PylonDeviceFeatureFromString(hDev,"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev,"TriggerMode","Off");CHECK(res);}/* For GigE cameras, we recommend increasing the packet size for better performance. If the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g., to 8192. In this sample, we only set the packet size to 1500. *//* ... Check first to see if the GigE camera packet size parameter is supported and if it is writable. */isAvail=PylonDeviceFeatureIsWritable(hDev,"GevSCPSPacketSize");if(isAvail){/* ... The device supports the packet size feature. Set a value. */res=PylonDeviceSetIntegerFeature(hDev,"GevSCPSPacketSize",1500);CHECK(res);}/* Determine the required size of the grab buffer. */{PYLON_STREAMGRABBER_HANDLEhGrabber;/* Temporary create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev,0,&hGrabber);CHECK(res);res=PylonStreamGrabberOpen(hGrabber);CHECK(res);res=PylonStreamGrabberGetPayloadSize(hDev,hGrabber,&payloadSize);CHECK(res);res=PylonStreamGrabberClose(hGrabber);CHECK(res);}/* Allocate memory for grabbing. */imgBuf=(unsignedchar*)malloc(payloadSize);if(NULL==imgBuf){fprintf(stderr,"Out of memory.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Grab some images in a loop. */for(i=0;i<numGrabs;++i){unsignedcharmin,max;PylonGrabResult_tgrabResult;_BoolbufferReady;/* Grab one single frame from stream channel 0. The camera is set to single frame acquisition mode. Wait up to 500 ms for the image to be grabbed. */res=PylonDeviceGrabSingleFrame(hDev,0,imgBuf,payloadSize,&grabResult,&bufferReady,500);if(GENAPI_E_OK==res&&!bufferReady){/* Timeout occurred. */printf("Frame %d: timeout\n",i+1);}CHECK(res);/* Check to see if the image was grabbed successfully. */if(grabResult.Status==Grabbed){/* Success. Perform image processing. */getMinMax(imgBuf,grabResult.SizeX,grabResult.SizeY,&min,&max);printf("Grabbed frame #%2d. Min. gray value = %3u, Max. gray value = %3u\n",i+1,min,max);#ifdef GENAPIC_WIN_BUILD/* Display image */res=PylonImageWindowDisplayImageGrabResult(0,&grabResult);CHECK(res);#endif}elseif(grabResult.Status==Failed){fprintf(stderr,"Frame %d wasn't grabbed successfully. Error code = 0x%08X\n",i+1,grabResult.ErrorCode);}}/* Clean up. Close and release the pylon device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);/* Free memory for grabbing. */free(imgBuf);pressEnterToExit();/* Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();returnEXIT_SUCCESS;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... Find out first how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve more details about the error. ... Find out first how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* Simple "image processing" function returning the minimum and maximum gray value of an 8 bit gray value image. */voidgetMinMax(constunsignedchar*pImg,int32_twidth,int32_theight,unsignedchar*pMin,unsignedchar*pMax){unsignedcharmin=255;unsignedcharmax=0;unsignedcharval;constunsignedchar*p;for(p=pImg;p<pImg+width*height;p++){val=*p;if(val>max)max=val;if(val<min)min=val;}*pMin=min;*pMax=max;}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/*This sample program demonstrates how to be informed about the removal of a device. Attention: If you build this sample in debug mode and run it using a GigE camera device, pylon will set the heartbeat timeout to 60 minutes. This is done to allow debugging and single stepping of the code without the camera thinking we're hung because we don't send any heartbeats. This also means that it would normally take 60 minutes for the application to notice that a GigE device has been disconnected. To work around this, the heartbeat timeout will be set to 1000 ms before we remove a device and wait to notice the removal.*/#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<string.h>#include<pylonc/PylonC.h>#ifdef __GNUC__#include<unistd.h># define Sleep(ms) usleep(ms*1000)#endifstaticintcallbackCounter=0;/* Will be incremented by the callback function. *//* Simple error handling */#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error messagefor the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);/* This function will be registered as a callback function that is calledwhen the opened device has been removed. On Windows only stdcall functions can be registered. */voidGENAPIC_CCremovalCallbackFunction(PYLON_DEVICE_HANDLEhDevice);/* Sets the heartbeat timeout. */int64_tsetHeartbeatTimeout(PYLON_DEVICE_HANDLEhDevice,int64_ttimeout_ms);intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_tnumDevices;/* Number of available devices. */PYLON_DEVICE_HANDLEhDev;/* Handle for the pylon device. */PYLON_DEVICECALLBACK_HANDLEhCb;/* Required for deregistering the callback. */intloopCount;/* Counter. */intisGigECamera;/* 1 if the device is a GigE device. *//* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all camera devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevices);CHECK(res);if(0==numDevices){fprintf(stderr,"No devices found.\n");/* Before exiting a program, PylonTerminate() should be called to release all pylon related resources. */PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Get a handle for the first device found. */res=PylonCreateDeviceByIndex(0,&hDev);CHECK(res);/* Before using the device, it must be opened. Open it for configuring parameters and for grabbing images. */res=PylonDeviceOpen(hDev,PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* Print out the name of the camera we are using. */{charbuf[256];size_tsiz=sizeof(buf);_BoolisReadable;isReadable=PylonDeviceFeatureIsReadable(hDev,"DeviceModelName");if(isReadable){res=PylonDeviceFeatureToString(hDev,"DeviceModelName",buf,&siz);CHECK(res);printf("Using camera %s\n",buf);}}/* Register the callback function. */res=PylonDeviceRegisterRemovalCallback(hDev,removalCallbackFunction,&hCb);CHECK(res);/* For GigE cameras, the application periodically sends heartbeat signals to the camera to keep the connection to the camera alive. If the camera doesn't receive heartbeat signals within the time period specified by the heartbeat timeout counter, the camera resets the connection. When the application is stopped by the debugger, the application cannot create the heartbeat signals. For that reason, the pylon runtime extends the heartbeat timeout when debugging to 5 minutes to allow debugging. For GigE cameras, we will set the heartbeat timeout to a shorter period before testing the callbacks. The heartbeat mechanism is also used for detection of device removal. When the pylon runtime doesn't receive an acknowledge for the heartbeat signal, it is assumed that the device has been removed. A removal callback will be fired in that case. By decreasing the heartbeat timeout, the surprise removal will be noticed earlier. */{/* Find out if we are using a GigE camera. */PylonDeviceInfo_tdevInfo;res=PylonDeviceGetDeviceInfo(hDev,&devInfo);CHECK(res);isGigECamera=0==strcmp(devInfo.DeviceClass,"BaslerGigE");/* Adjust the heartbeat timeout. */if(isGigECamera){setHeartbeatTimeout(hDev,1000);/* 1000 ms */}}/* Ask the user to disconnect a device. */loopCount=20*4;printf("Please disconnect the device (timeout %d s) \n",loopCount/4);/* Wait until the removal has been noticed and callback function has been fired. */do{/* Print a . every few seconds to tell the user we're waiting for the callback. */if(--loopCount%4==0){printf(".");fflush(stdout);}Sleep(250);}while(callbackCounter<1&&loopCount>=0);/* Check loopCount so we won't wait forever. */if(callbackCounter<1)printf("\nTimeout expired. Device hasn't been removed.\n");/* Clean up. *//* ... Deregister the removal callback. */res=PylonDeviceDeregisterRemovalCallback(hDev,hCb);CHECK(res);/* ....Close and release the pylon device. */res=PylonDeviceClose(hDev);CHECK(res);res=PylonDestroyDevice(hDev);CHECK(res);/* Shut down the pylon runtime system. Don't call any pylon method after calling PylonTerminate(). */PylonTerminate();pressEnterToExit();returnEXIT_SUCCESS;}/* The function to be called when the removal of an opened device is detected. */voidGENAPIC_CCremovalCallbackFunction(PYLON_DEVICE_HANDLEhDevice){PylonDeviceInfo_tdi;GENAPIC_RESULTres;/* Print out the name of the device. It is not possible to read the name from the camera since it has been removed. Use the device's device information instead. For accessing the device information, no reading from the device is required. *//* Retrieve the device information for the removed device. */res=PylonDeviceGetDeviceInfo(hDevice,&di);CHECK(res);/* Print out the name. */printf("\nCallback function for removal of device %s (%s).\n",di.FriendlyName,di.FullName);/* Increment the counter to indicate that the callback has been fired. */callbackCounter++;}/* If the device provides a heartbeat timeout, this function will set the heartbeat timeout. When the device provides the parameter, the old value is returned, -1 otherwise. The heartbeat timeout is a parameter provided by the transport layer. The transport layer parameters are exposed as a GenApi node map that can be retrieved from the device.*/int64_tsetHeartbeatTimeout(PYLON_DEVICE_HANDLEhDev,int64_ttimeout_ms){NODEMAP_HANDLEhNodemap;/* Handle to the node map */NODE_HANDLEhNode;/* Handle to a node, i.e., a feature */GENAPIC_RESULTres;/* Return value */int64_toldTimeout;/* The current timeout value *//* Get the node map for the transport layer parameters. */res=PylonDeviceGetTLNodeMap(hDev,&hNodemap);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNodemap){/* The device doesn't provide a transport layer node map. Nothing to do. */return-1;}/* Get the node for the heartbeat timeout parameter. */res=GenApiNodeMapGetNode(hNodemap,"HeartbeatTimeout",&hNode);CHECK(res);if(GENAPIC_INVALID_HANDLE==hNode){/* There is no heartbeat timeout parameter. Nothing to do. */return-1;}/* Get the current value. */res=GenApiIntegerGetValue(hNode,&oldTimeout);CHECK(res);/* Set the new value. */res=GenApiIntegerSetValue(hNode,timeout_ms);CHECK(res);/* Return the old value. */returnoldTimeout;}/* This function demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;size_tlength;/* Retrieve the error message. ... Find out first how big the buffer must be, */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorMessage(errMsg,&length);fprintf(stderr,"%s (%#08x).\n",errMsg,(unsignedint)errc);free(errMsg);/* Retrieve more details about the error. ... Find out first how big the buffer must be, */GenApiGetLastErrorDetail(NULL,&length);errMsg=(char*)malloc(length);/* ... and retrieve the message. */GenApiGetLastErrorDetail(errMsg,&length);fprintf(stderr,"%s\n",errMsg);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}
/* This sample illustrates how to grab images using a GigE Vision action command to trigger multiple cameras. At least 2 connected GigE cameras are required for this sample.*/#ifndef _WIN32_WINNT# define _WIN32_WINNT 0x0400#endif#include<stdlib.h>#include<stdio.h>#include<malloc.h>#include<string.h>#include<time.h>#include<pylonc/PylonC.h>/* Limits the amount of cameras used for grabbing.It is important to manage the available bandwidth when grabbing with multiplecameras. This applies, for instance, if two GigE cameras are connected to thesame network adapter via a switch. To manage the bandwidth, the GevSCPDinterpacket delay parameter and the GevSCFTD transmission delay parameter canbe set for each GigE camera device. The "Controlling Packet Transmission Timingwith the Interpacket and Frame Transmission Delays on Basler GigE Vision Cameras"Application Note (AW000649xx000) provides more information about this topic. */#define MAX_NUM_DEVICES 4#define GIGE_PACKET_SIZE 1500 /* Size of one Ethernet packet. */#define GIGE_PROTOCOL_OVERHEAD 36 /* Total number of bytes of protocol overhead. */#define CHECK( errc ) if ( GENAPI_E_OK != errc ) printErrorAndExit( errc )constuint32_tAllGroupMask=0xffffffff;/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void);/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc);intmain(void){GENAPIC_RESULTres;/* Return value of pylon methods. */size_ti;/* Generic loop variable */size_tnumDevicesEnumerated;/* Number of available devices. */size_tnumDevicesToUse;/* Number of usable devices. */_BoolisAvail;/* Used for checking feature availability. */size_tdeviceIndex;/* Index of device used in this sample. */PYLON_WAITOBJECTS_HANDLEwos=NULL;/* Wait objects. */uint32_tDeviceKey;/* Random device key used in this session. It will be initialized below. */uint32_tGroupKey;/* Group key for the devices. In this sample all devices will be in the same group. *//* These are camera-specific variables. */PYLON_DEVICE_HANDLEhDev[MAX_NUM_DEVICES];/* Handle for the pylon device. */PYLON_STREAMGRABBER_HANDLEhGrabber[MAX_NUM_DEVICES];/* Handle for the pylon stream grabber. */unsignedchar*buffers[MAX_NUM_DEVICES];/* Buffers used for grabbing. */PYLON_STREAMBUFFER_HANDLEbufHandles[MAX_NUM_DEVICES];/* Handles for the buffers. */PylonDeviceInfo_tdeviceInfos[MAX_NUM_DEVICES];/* Information about enumerated devices *//* Seed the random number generator. */srand((unsignedint)time(NULL));/* Get random device key used in this session. */DeviceKey=rand();/* In this sample all cameras will belong to the same group. */GroupKey=0x24;/* Before using any pylon methods, the pylon runtime must be initialized. */PylonInitialize();/* Enumerate all devices. You must call PylonEnumerateDevices() before creating a device. */res=PylonEnumerateDevices(&numDevicesEnumerated);CHECK(res);if(numDevicesEnumerated==0){fprintf(stdout,"No devices found!\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Create wait objects so we can wait for the images of each camera */res=PylonWaitObjectsCreate(&wos);CHECK(res);/* ======================================================================= * Open Cameras and Set Parameters. * ======================================================================= */for(deviceIndex=0;deviceIndex<numDevicesEnumerated;++deviceIndex){PylonDeviceInfo_tdi;res=PylonGetDeviceInfo(deviceIndex,&di);CHECK(res);if(strcmp(di.DeviceClass,"BaslerGigE")!=0){/* Action commands are only supported by GigE cameras. */continue;}/* Get a handle for the device. */res=PylonCreateDeviceByIndex(deviceIndex,&hDev[deviceIndex]);CHECK(res);/* Before using the device, it must be opened. Open it for setting parameters and for grabbing images. */res=PylonDeviceOpen(hDev[deviceIndex],PYLONC_ACCESS_MODE_CONTROL|PYLONC_ACCESS_MODE_STREAM);CHECK(res);/* When the device has been opened successfully, we remember its deviceinfo so we can print out the name device name, etc. later */deviceInfos[deviceIndex]=di;/* Print out the name of the camera we are using. */printf("Using camera '%s'\n",deviceInfos[deviceIndex].ModelName);isAvail=PylonDeviceFeatureIsAvailable(hDev[deviceIndex],"ActionControl");if(!isAvail){/* Action Command feature is not available. */fprintf(stderr,"Device doesn't support the Action Control");PylonTerminate();pressEnterToExit();exit(EXIT_SUCCESS);}/* Configure the first action (Action1)*/res=PylonDeviceSetIntegerFeatureInt32(hDev[deviceIndex],"ActionSelector",1);CHECK(res);res=PylonDeviceSetIntegerFeatureInt32(hDev[deviceIndex],"ActionDeviceKey",DeviceKey);CHECK(res);res=PylonDeviceSetIntegerFeatureInt32(hDev[deviceIndex],"ActionGroupKey",GroupKey);CHECK(res);res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"ActionGroupMask",AllGroupMask);CHECK(res);/* Set the trigger mode to FrameStart and TriggerSource to first action. */res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerSelector","FrameStart");CHECK(res);res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerMode","On");CHECK(res);res=PylonDeviceFeatureFromString(hDev[deviceIndex],"TriggerSource","Action1");/* Action1 corresponds to ActionSelector=1. */CHECK(res);/* Set the pixel format to Mono8, where gray values will be output as 8-bit values for each pixel. *//* ... First check to see if the device supports the Mono8 format. */isAvail=PylonDeviceFeatureIsAvailable(hDev[deviceIndex],"EnumEntry_PixelFormat_Mono8");if(!isAvail){/* Feature is not available. */fprintf(stderr,"Device doesn't support the Mono8 pixel format.\n");PylonTerminate();pressEnterToExit();exit(EXIT_SUCCESS);}/* ... Set the pixel format to Mono8. */res=PylonDeviceFeatureFromString(hDev[deviceIndex],"PixelFormat","Mono8");CHECK(res);/* For GigE cameras, we recommend increasing the packet size for better performance. When the network adapter supports jumbo frames, set the packet size to a value > 1500, e.g. to 8192. In this sample, we only set the packet size to 1500. Also we set the Inter-Packet and the Frame Transmission delay so that the switch can line up packets in a better way. */res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"GevSCPSPacketSize",GIGE_PACKET_SIZE);CHECK(res);res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"GevSCPD",(GIGE_PACKET_SIZE+GIGE_PROTOCOL_OVERHEAD)*(MAX_NUM_DEVICES-1));CHECK(res);res=PylonDeviceSetIntegerFeature(hDev[deviceIndex],"GevSCFTD",(GIGE_PACKET_SIZE+GIGE_PROTOCOL_OVERHEAD)*deviceIndex);CHECK(res);}/* Remember the number of devices actually created. */numDevicesToUse=deviceIndex;if(numDevicesToUse==0){fprintf(stderr,"No suitable cameras found!\n");PylonTerminate();pressEnterToExit();exit(EXIT_SUCCESS);}if(numDevicesToUse<2){printf("WARNING: This sample works best with two or more GigE cameras supporting action commands.\n");}/* ====================================================================== Allocate and Register Buffers for Grab. ====================================================================== */for(deviceIndex=0;deviceIndex<numDevicesToUse;++deviceIndex){PYLON_WAITOBJECT_HANDLEhWait;size_tpayloadSize;/* Image grabbing is done using a stream grabber. A device may be able to provide different streams. A separate stream grabber must be used for each stream. In this sample, we create a stream grabber for the default stream, i.e., the first stream ( index == 0 ). *//* Get the number of streams supported by the device and the transport layer. */res=PylonDeviceGetNumStreamGrabberChannels(hDev[deviceIndex],&i);CHECK(res);if(i<1){fprintf(stderr,"The transport layer doesn't support image streams.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* Create and open a stream grabber for the first channel. */res=PylonDeviceGetStreamGrabber(hDev[deviceIndex],0,&hGrabber[deviceIndex]);CHECK(res);res=PylonStreamGrabberOpen(hGrabber[deviceIndex]);CHECK(res);/* Get a handle for the stream grabber's wait object. The wait object allows waiting for buffers to be filled with grabbed data. */res=PylonStreamGrabberGetWaitObject(hGrabber[deviceIndex],&hWait);CHECK(res);/* Add the stream grabber's wait object to our wait objects. This is needed to be able to wait until at least one camera has grabbed an image in the grab loop below. */res=PylonWaitObjectsAdd(wos,hWait,NULL);CHECK(res);/* Determine the required size of the grab buffer. */res=PylonStreamGrabberGetPayloadSize(hDev[deviceIndex],hGrabber[deviceIndex],&payloadSize);CHECK(res);/* Allocate memory for grabbing. */buffers[deviceIndex]=(unsignedchar*)malloc(payloadSize);if(NULL==buffers[deviceIndex]){fprintf(stderr,"Out of memory.\n");PylonTerminate();pressEnterToExit();exit(EXIT_FAILURE);}/* We must tell the stream grabber the number and size of the buffers we are using. *//* .. We will use one buffer for grabbing. */res=PylonStreamGrabberSetMaxNumBuffer(hGrabber[deviceIndex],1);CHECK(res);/* .. We will not use buffers bigger than payloadSize bytes. */res=PylonStreamGrabberSetMaxBufferSize(hGrabber[deviceIndex],payloadSize);CHECK(res);/* Allocate the resources required for grabbing. After this, critical parameters that impact the payload size must not be changed until FinishGrab() is called. */res=PylonStreamGrabberPrepareGrab(hGrabber[deviceIndex]);CHECK(res);/* Before using the buffers for grabbing, they must be registered at the stream grabber. For each registered buffer, a buffer handle is returned. After registering, these handles are used instead of the raw pointers. */res=PylonStreamGrabberRegisterBuffer(hGrabber[deviceIndex],buffers[deviceIndex],payloadSize,&bufHandles[deviceIndex]);CHECK(res);/* Feed the buffers into the stream grabber's input queue. For each buffer, the API allows passing in a pointer to additional context information. This pointer will be returned unchanged when the grab is finished. In our example, we use the index of the camera as context information. */res=PylonStreamGrabberQueueBuffer(hGrabber[deviceIndex],bufHandles[deviceIndex],(void*)deviceIndex);CHECK(res);}/* The stream grabber is now prepared. As soon as the camera starts acquiring images, the image data will be grabbed into the provided buffers. */for(deviceIndex=0;deviceIndex<numDevicesToUse;++deviceIndex){/* Let the camera acquire images. */res=PylonDeviceExecuteCommandFeature(hDev[deviceIndex],"AcquisitionStart");/* Do not call CHECK() here! Instead exit the loop. */if(res!=GENAPI_E_OK){break;}}/* ====================================================================== Issue an ActionCommand and Retrieve the Images. ====================================================================== *//* Only start the grab loop if all cameras have been "started" */if(res==GENAPI_E_OK){charsubnet[32]={'\0'};/* reserve space for a dotted ip address */size_tbuflen=sizeofsubnet;PYLON_DEVICE_INFO_HANDLEhDevInfo=NULL;/* Retrieve subnet broadcast address of first device. We must query this GigE specific value explicitly as it isn't contained in the generic PylonDeviceInfo_t struct. */res=PylonDeviceGetDeviceInfoHandle(hDev[0],&hDevInfo);CHECK(res);res=PylonDeviceInfoGetPropertyValueByName(hDevInfo,"SubnetAddress",subnet,&buflen);CHECK(res);/* Trigger the camera using an action command. */res=PylonGigEIssueActionCommand(DeviceKey,GroupKey,AllGroupMask,subnet,0,NULL,NULL);CHECK(res);/* Grab one image from each camera. */for(deviceIndex=0;deviceIndex<numDevicesToUse;++deviceIndex){_BoolisReady;size_twoIndex=0;PylonGrabResult_tgrabResult;/* Wait for the next buffer to be filled. Wait up to 5000 ms.*/res=PylonWaitObjectsWaitForAny(wos,5000,&woIndex,&isReady);CHECK(res);if(!isReady){/* Timeout occurred. *//* Grab timeout occurred. */fprintf(stderr,"Grab timeout occurred.\n");break;/* Stop grabbing. */}/* The woIndex corresponds to the index of the camera in handle arrays. *//* Retrieve the grab result. */res=PylonStreamGrabberRetrieveResult(hGrabber[woIndex],&grabResult,&isReady);CHECK(res);if(!isReady){/* Oops. No grab result available? We should never have reached this point. Since the wait operation above returned without a timeout, a grab result should be available. */fprintf(stderr,"Failed to retrieve a grab result\n");break;}/* Check to see whether the image was grabbed successfully. */if(grabResult.Status==Grabbed&&grabResult.PayloadType==PayloadType_Image){/* Success. Perform image processing. Since we passed more than one buffer to the stream grabber, the remaining buffers are filled while we are doing the image processing. The processed buffer won't be touched by the stream grabber until we pass it back to the stream grabber. *//* Pointer to the buffer attached to the grab result. Get the buffer pointer from the result structure. Since we also got the buffer index, we could alternatively use buffers[bufferIndex]. *//* Unsigned char* buffer = (unsigned char*) grabResult.pBuffer; *//* Perform processing. */printf("Grabbed frame from camera %u into buffer.\n",(unsignedint)woIndex);#ifdef GENAPIC_WIN_BUILD/* Display image. */if(woIndex<=31){res=PylonImageWindowDisplayImageGrabResult(woIndex,&grabResult);CHECK(res);}#endif}elseif(grabResult.Status==Failed){/* If a buffer has been incompletely grabbed, the network bandwidth is possibly insufficient for transferring multiple images simultaneously. See note on MAX_NUM_DEVICES. */fprintf(stderr,"Frame wasn't grabbed successfully. Error code = 0x%08X\n",grabResult.ErrorCode);}}/* for */}/* ======================================================================== Clean up. ======================================================================== *//* Stop the image acquisition on the cameras. */for(deviceIndex=0;deviceIndex<numDevicesToUse;++deviceIndex){/* ... Stop the camera. */res=PylonDeviceExecuteCommandFeature(hDev[deviceIndex],"AcquisitionStop");CHECK(res);}/* Remove all wait objects from waitobjects. */res=PylonWaitObjectsRemoveAll(wos);CHECK(res);res=PylonWaitObjectsDestroy(wos);CHECK(res);/* Do the cleanup for each camera we've set up. */for(deviceIndex=0;deviceIndex<numDevicesToUse;++deviceIndex){_Boolrdy;PylonGrabResult_tgrabResult;/* Issue a flush call to ensure that all queued buffers are put into the stream grabber's output queue. */res=PylonStreamGrabberFlushBuffersToOutput(hGrabber[deviceIndex]);CHECK(res);/* The buffers can now be retrieved from the stream grabbers output queue. */do{res=PylonStreamGrabberRetrieveResult(hGrabber[deviceIndex],&grabResult,&rdy);CHECK(res);}while(rdy);/* After all buffers have been retrieved from the stream grabber, they can be deregistered. After deregistering the buffers, it is safe to free the memory. */res=PylonStreamGrabberDeregisterBuffer(hGrabber[deviceIndex],bufHandles[deviceIndex]);CHECK(res);free(buffers[deviceIndex]);/* Release grabbing related resources. */res=PylonStreamGrabberFinishGrab(hGrabber[deviceIndex]);CHECK(res);/* When PylonStreamGrabberFinishGrab() has been called, parameters that impact the payload size (e.g., the AOI width and height parameters) are unlocked and can be modified again. *//* Close the stream grabber. */res=PylonStreamGrabberClose(hGrabber[deviceIndex]);CHECK(res);/* Close and release the pylon device. The stream grabber becomes invalid after closing the pylon device. Don't call stream grabber related methods after closing or releasing the device. */res=PylonDeviceClose(hDev[deviceIndex]);CHECK(res);res=PylonDestroyDevice(hDev[deviceIndex]);CHECK(res);}pressEnterToExit();/* ... Shut down the pylon runtime system. Don't call any pylon function after calling PylonTerminate(). */PylonTerminate();returnEXIT_SUCCESS;}/* This method demonstrates how to retrieve the error message for the last failed function call. */voidprintErrorAndExit(GENAPIC_RESULTerrc){char*errMsg;char*errDetail;size_tlength=0;/* Retrieve the error message using double calling. */GenApiGetLastErrorMessage(NULL,&length);errMsg=(char*)malloc(length);GenApiGetLastErrorMessage(errMsg,&length);/* Get the detailed error message. */length=0;GenApiGetLastErrorDetail(NULL,&length);errDetail=(char*)malloc(length);GenApiGetLastErrorDetail(errDetail,&length);fprintf(stderr,"%s (%#08x).\n%s\n",errMsg,(unsignedint)errc,errDetail);free(errDetail);free(errMsg);PylonTerminate();/* Releases all pylon resources. */pressEnterToExit();exit(EXIT_FAILURE);}/* This function can be used to wait for user input at the end of the sample program. */voidpressEnterToExit(void){fprintf(stderr,"\nPress enter to exit.\n");while(getchar()!='\n');}