AxsunOCTCapture  3.6.0.0
Captures and buffers streamed imaged data from the Axsun Ethernet/PCIe DAQ and displays or retrieves images to a client application on request.
AxsunOCTCapture_Cpp_linux_example.cpp

This is example source code showing how to use the image capture functionality of AxsunOCTCapture in a C++ client application (Linux OS).

// AxsunOCTCapture_Cpp_linux_example.cpp : This file contains the 'main' function. Program execution begins and ends there.
// include for all AxsunOCTCapture functions, structs, enums, typedefs
// STL includes for this example application; NOT related to AxsunOCTCapture functionality
#include <iostream> // for std::cout, std::cin
#include <chrono> // for loop timer sleep function
#include <thread> // for loop timer sleep function
#include <vector> // for user buffer in which to copy data
#include <filesystem> // for managing save/export paths
#include <algorithm> // for std::for_each
using namespace std::chrono_literals;
//
// NOTES:
//
// 1. AxsunOCTCapture functions are Standard C and do NOT throw C++ exceptions, but rather
// return an error status of type AxErr. Calls to AxsunOCTCapture functions in this
// example program are typically wrapped in an "if (status != OK) throw AxErr" fashion
// and contained in a try/catch block in order to make the behavior exception-based.
//
// 2. The intent of this example program is to exemplify the capabilities of the
// AxsunOCTCapture library. Program structure is simplified for readability and is NOT
// appropriate for "production" code without some refactoring.
//
// Define an AxsunOCTCapture class to wrap axStartSession(), axStopSession(), and the session handle in RAII fashion.
// (This will convieniently call axStopSession() automatically in the destructor so that resources are cleaned up.)
class AxsunOCTCapture {
private:
AOChandle session_{ nullptr }; // AOChandle is an opaque struct
public:
AxsunOCTCapture(int32_t size) { if (auto retval = axStartSession(&session_, size); retval != AxErr::NO_AxERROR) throw retval; }
~AxsunOCTCapture() { axStopSession(session_); }
AOChandle operator()() { if (session_) return session_; else throw AxErr::CAPTURE_SESSION_NOT_SETUP; }
};
// Global variables for synchronization
// (Please use thread-safe synchronization methods for production code!)
auto imaging_global = bool{ false };
auto record_complete = bool{ false };
// Function to print changes in DAQ/buffer state
void DAQStateCallback(uint32_t state, void* userdata) {
std::cout << "callback: "; // not a thread-safe use of std::cout (not production code!)
switch (static_cast<AxDAQEvent>(state)) {
std::cout << "DAQ/buffer state -> STOPPED\n";
imaging_global = false;
break;
std::cout << "DAQ/buffer state -> IMAGING\n";
imaging_global = true;
break;
std::cout << "DAQ/buffer state -> RECORD COMPLETE\n";
record_complete = true;
break;
std::cout << "DAQ/buffer state -> RECORDING\n";
break;
std::cout << "DAQ/buffer state -> LOADING COMPLETE\n";
break;
std::cout << "DAQ/buffer state -> LOADING FROM DISK\n";
break;
}
}
void ExportCallback(uint32_t image, void* userdata) {
if (!(image % 10)) // report every 10th image
std::cout << "callback: Exported image: " << image << "\n"; // not a thread-safe use of cout (not production code!)
}
int main() {
char message[512]{""}; // for getting string output from axGetMessage() and axGetErrorString()
try {
std::cout << "Welcome to the AxsunOCTCapture Example Console Application.\n";
// create an AxsunOCTCapture session
// (this is the first step in any AxsunOCTCapture application)
auto AOC = AxsunOCTCapture{ 250 }; // argument is buffer size in MB
// register callback functions for: 1) change in DAQ/buffer imaging state, and 2) image export progress
// (using callback functionality is optional but enables more advanced client program architectures)
axRegisterDAQCallback(AOC(), DAQStateCallback, nullptr);
axRegisterExportCallback(AOC(), ExportCallback, nullptr);
// select Ethernet capture interface for this session
// (requires elevated privledges on Linux OS)
if (auto retval = axSelectInterface(AOC(), AxInterface::GIGABIT_ETHERNET); retval != AxErr::NO_AxERROR) throw retval;
// print message describing current capture interface status
if (auto retval = axGetMessage(AOC(), message); retval != AxErr::NO_AxERROR) throw retval;
std::cout << message << '\n';
// declare local variables for axGetStatus()
uint32_t imaging{ 0 }, last_packet{ 0 }, last_frame{ 0 }, last_image{ 0 }, dropped_packets{ 0 }, frames_since_sync{ 0 };
// declare local variables for axGetImageInfo() and axRequestImage()
auto prefs = request_prefs_t{
.crop_width_total = 2000
};
auto info = image_info_t{};
// allocate a large enough user buffer to cover image sizes up to 2048 x 2000 x 4 bytes/pix
// (resize appropriately depending on your application)
constexpr auto buffer_size = size_t{ 2048 * 2000 * 4 };
auto image_buffer = std::vector<uint8_t>(buffer_size); // could use C-style array if preferred here
auto counter = int32_t{ 0 };
// Demonstrate the AxsunOCTCapture IMAGE ACQUISITION functionality until
// a BURST RECORD operation has completed (or a timeout occurs @ 1000 loops)
while (!record_complete && counter < 1000) {
// NOTE: using executable based on the AxsunOCTControl_LW API:
// TURN ON LASER EMISSION,
// TURN ON/OFF DAQ Live Imaging mode,
// START BURST RECORD operation,
// etc...
// check Main Image Buffer status
if (auto retval = axGetStatus(AOC(), &imaging, &last_packet, &last_frame, &last_image, &dropped_packets, &frames_since_sync); retval != AxErr::NO_AxERROR) throw retval;
// enable & disable axGetImageInfo() & axRequestImage() functionality based on flag set in DAQcallback
// (these are the two "core functions" for retrieving images from the library into the client app)
if (imaging_global) {
// get image info on most recent image enqueued in the buffer
if (auto retval = axGetImageInfo(AOC(), MOST_RECENT_IMAGE, &info); retval != AxErr::NO_AxERROR) {
if (retval != AxErr::DATA_NOT_FOUND_IN_BUFFER && retval != AxErr::DATA_RETURNED_IN_PREVIOUS_REQUEST) {
// get and then print error details
axGetErrorString(retval, message);
std::cout << "axGetImageInfo() returned " << static_cast<int32_t>(retval) << " " << message << '\n';
}
}
else {
// if no errors in axGetImageInfo() then request the image to be copied into client's image_buffer
retval = axRequestImage(AOC(), info.image_number, prefs, buffer_size, image_buffer.data(), &info);
// here is where you can save, display, analyze, or otherwise //
// do whatever you want with the data now in your image_buffer! //
// print some statistics every 25th iteration
if (!(counter % 25)) {
std::cout << "Image number: " << info.image_number << ", Width: " << info.width <<", Drops: " << dropped_packets;
if (info.force_trig) std::cout << " *** FORCE TRIGGERED ***";
if (info.trig_too_fast) std::cout << " *** TRIGGER TOO FAST ***";
std::cout << '\n';
}
else { // otherwise print some of the image pixels to the console
;// std::for_each_n(image_buffer.data(), 10, [](const auto x) {std::cout << "\t" << +x; });
}
//std::cout << '\n';
}
}
else {
if (!(counter % 50)) { // print every 50th iteration
std::cout << counter << "\tImaging is off. Turn on laser emission and set DAQ to Imaging On mode.\n";
}
}
// increment loop counter
++counter;
// loop timer for approximately 50 fps update rate
std::this_thread::sleep_for(20ms);
}
std::cout << "Exiting imaging loop...\n\n";
// Demonstrate the SAVE, LOAD, and EXPORT functionality
// if a BURST RECORD operation was just completed
if (record_complete) {
auto tempnumber = int32_t{ 0 }; // a temp variable for passing by pointer to Save, Load, and Export functions
// initialize some paths for saved buffer and exported image files
// (should end up in "/tmp/Axsun/OCT_Files/" unless overriden by OS environment variable)
auto parent_path = std::filesystem::temp_directory_path() / "Axsun" / "OCT_Files";
auto savefile = parent_path / "example_savefile.dat";
auto export_dir = parent_path / "Exported";
// report images recorded by checking buffer status (i.e. the "last_image" argument)
if (auto retval = axGetStatus(AOC(), &imaging, &last_packet, &last_frame, &last_image, &dropped_packets, &frames_since_sync); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "There are now " << last_image << " images in the Main Image Buffer.\n"; // should be same as number of images just burst recorded
// SAVE the datafile to disk
if (auto retval = axSaveFile(AOC(), savefile.c_str(), 0, &tempnumber); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "Saved " << tempnumber << " packets to " << savefile << "\n";
// CLEAR the main image buffer and show status
if (auto retval = axResizeBuffer(AOC(), 0); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "Main Image Buffer cleared.\n";
if (auto retval = axGetStatus(AOC(), &imaging, &last_packet, &last_frame, &last_image, &dropped_packets, &frames_since_sync); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "There are now " << last_image << " images in the Main Image Buffer.\n"; // should be = 0
// LOAD the same datafile back from disk and show buffer status
if (auto retval = axLoadFile(AOC(), savefile.c_str(), &tempnumber); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "Loaded " << tempnumber << " packets from disk.\n"; // should be same as number of packets saved earlier
if (auto retval = axGetStatus(AOC(), &imaging, &last_packet, &last_frame, &last_image, &dropped_packets, &frames_since_sync); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "There are now " << last_image << " images in the Main Image Buffer.\n"; // should be same as number of images recorded
// EXPORT individual images using axExportImages()
// (this is a "simple" version with minimal adjustability)
// if (auto retval = axExportImages(AOC(), export_dir, &tempnumber, AxFileType::PNG); retval != AxErr::NO_AxERROR) throw retval;
// EXPORT individual images using axExportImagesAdv()
// (this is an advanced version which passes two preferences structures for maximum adjustability)
auto request_prefs = request_prefs_t{ .average_number = 1 };
auto export_prefs = export_prefs_t{
.width = 1024,
.height = 256,
.contrast = 1.0,
.brightness = 0.0,
.colormap = AxColormap::SEPIA,
.movie_fps = 60
};
if (auto retval = axExportImagesAdv(AOC(), export_dir.c_str(), &tempnumber, AxFileType::PNG, 1, 100, request_prefs, export_prefs); retval != AxErr::NO_AxERROR) throw retval;
std::cout << "Exported " << tempnumber << " individual images to " << export_dir << "\n";
}
}
catch (const AxErr& e) {
axGetErrorString(e, message);
std::cout << "ERROR: " << message << '\n';
}
catch (...) {
std::cout << "***** UNKNOWN ERROR. Program terminating.\n";
}
std::cout << "Done.\n\n";
}
axGetImageInfo
AxErr axGetImageInfo(AOChandle session, uint32_t requested_image, image_info_t *image_info)
Get information on an image in the Main Image Buffer.
axSaveFile
AxErr axSaveFile(AOChandle session, const char *path_file, uint8_t full_buffer, int32_t *packets_written)
Save contents of Main Image Buffer to disk.
AOChandle
struct CaptureSession * AOChandle
Axsun OCT Capture handle - a pointer to the opaque structure used to manage created capture sessions.
Definition: AxsunOCTCapture.h:132
IMAGING_START
@ IMAGING_START
Definition: AxsunOCTCapture.h:205
LOAD_START
@ LOAD_START
Definition: AxsunOCTCapture.h:217
axStopSession
AxErr axStopSession(AOChandle session)
Stop a capture session and deallocate all resources, including Main Image Buffer and interfaces.
AxDAQEvent
AxDAQEvent
Types of transitions in DAQ's operational mode, conveyed via user callback function....
Definition: AxsunOCTCapture.h:201
RECORD_START
@ RECORD_START
Definition: AxsunOCTCapture.h:209
request_prefs_t::request_mode
AxRequestMode request_mode
Definition: AxsunOCTCapture.h:329
axResizeBuffer
AxErr axResizeBuffer(AOChandle session, float capacity_MB)
Clears and resets the Main Image Buffer, optionally with a new buffer size.
IMAGING_STOP
@ IMAGING_STOP
Definition: AxsunOCTCapture.h:203
RECORD_DONE
@ RECORD_DONE
Definition: AxsunOCTCapture.h:207
axGetErrorString
void axGetErrorString(AxErr errorcode, char *message_out)
Get a description of a specific AxErr error code.
LOAD_DONE
@ LOAD_DONE
Definition: AxsunOCTCapture.h:215
axRegisterDAQCallback
AxErr axRegisterDAQCallback(AOChandle session, AxCallbackFunction_t callback_function, void *user_data)
Registers a callback function to be executed upon a change in the DAQ imaging state (e....
axGetMessage
AxErr axGetMessage(AOChandle session, char *message_out)
Get a description of the capture session's interface status.
axRegisterExportCallback
AxErr axRegisterExportCallback(AOChandle session, AxCallbackFunction_t callback_function, void *user_data)
Registers a callback function to be executed each time an image is exported using axExportImages() or...
axGetStatus
AxErr axGetStatus(AOChandle session, uint32_t *imaging, uint32_t *last_packet_in, uint32_t *last_frame_in, uint32_t *last_image_in, uint32_t *dropped_packets, uint32_t *frames_since_sync)
Get imaging mode status and Main Image Buffer statistics.
image_info_t
Structure for conveying metadata information about an image.
Definition: AxsunOCTCapture.h:392
export_prefs_t::width
uint32_t width
Definition: AxsunOCTCapture.h:361
RETRIEVE_TO_CALLER
@ RETRIEVE_TO_CALLER
Definition: AxsunOCTCapture.h:187
export_prefs_t
Structure for image export preferences (movie functionality requires installation of OpenCV).
Definition: AxsunOCTCapture.h:359
axRequestImage
AxErr axRequestImage(AOChandle session, uint32_t requested_image, request_prefs_t prefs, uint32_t output_buf_len, uint8_t *image_data_out, image_info_t *image_info)
Retrieve and/or display an image from the Main Image Buffer.
AxErr
AxErr
Error codes returned from AxsunOCTCapture or AxsunOCTControl_LW functions. Use axGetErrorString() in ...
Definition: AxsunCommonEnums.h:34
axExportImagesAdv
AxErr axExportImagesAdv(AOChandle session, const char *path_directory, int32_t *images_exported, AxFileType file_type, uint32_t start_image, uint32_t end_image, request_prefs_t request_prefs, export_prefs_t export_prefs)
Export images from the Main Image Buffer into individual graphics and movie files,...
axSelectInterface
AxErr axSelectInterface(AOChandle session, AxInterface which_interface)
Select the data interface (Ethernet, PCIe, or none) for the capture session.
AxsunOCTCapture.h
This header file contains all exported function prototypes, structures, and enums necessary for integ...
axStartSession
AxErr axStartSession(AOChandle *session, float capacity_MB)
Start an Axsun DAQ imaging session by allocating memory for the Main Image Buffer.
request_prefs_t::average_number
uint32_t average_number
Definition: AxsunOCTCapture.h:333
axLoadFile
AxErr axLoadFile(AOChandle session, const char *path_file, int32_t *packets_read)
Load contents from file on disk into Main Image Buffer.
request_prefs_t
Structure for image request preferences.
Definition: AxsunOCTCapture.h:326
PNG
@ PNG
Definition: AxsunOCTCapture.h:173
GIGABIT_ETHERNET
@ GIGABIT_ETHERNET
Definition: AxsunOCTCapture.h:227