71 std::string ensureNewName(std::string name)
75 std::ifstream file(name);
85 size_t i=name.rfind(
'.');
86 if (i != name.npos && name.size()-i <= 4)
88 suffix=name.substr(i);
89 name=name.substr(0, i);
98 s << name <<
"_" << n << suffix;
119 std::string storeBuffer(
const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
120 const std::shared_ptr<GenApi::CChunkAdapter> &chunkadapter,
121 const std::string &component,
const rcg::Buffer *buffer, uint32_t part)
130 name <<
"image_" << t_sec <<
"." << std::setfill(
'0') << std::setw(9) << t_nsec;
132 if (component.size() > 0)
134 name <<
'_' << component;
141 bool out1 = line_status & 0x01;
142 bool out2 = line_status & 0x02;
143 name <<
"_" << std::noboolalpha << out1 <<
"_" << out2;
152 const unsigned char *p=
static_cast<const unsigned char *
>(buffer->
getBase(part));
164 std::ofstream out(ensureNewName(name.
str()), std::ios::binary);
166 out <<
"P5" << std::endl;
167 out << width <<
" " << height << std::endl;
170 std::streambuf *sb=out.rdbuf();
172 for (
size_t k=0; k<height && out.good(); k++)
174 for (
size_t i=0; i<width; i++)
176 sb->sputc(static_cast<char>(*p++));
189 std::ofstream out(ensureNewName(name.
str()), std::ios::binary);
191 out <<
"P5" << std::endl;
192 out << width <<
" " << height << std::endl;
193 out << 65535 <<
"\n";
195 std::streambuf *sb=out.rdbuf();
201 for (
size_t k=0; k<height && out.good(); k++)
203 for (
size_t i=0; i<width; i++)
205 sb->sputc(static_cast<char>(*p++));
206 sb->sputc(static_cast<char>(*p++));
214 for (
size_t k=0; k<height && out.good(); k++)
216 for (
size_t i=0; i<width; i++)
218 sb->sputc(static_cast<char>(p[1]));
219 sb->sputc(static_cast<char>(p[0]));
234 std::ofstream out(ensureNewName(name.
str()), std::ios::binary);
236 out <<
"P6" << std::endl;
237 out << width <<
" " << height << std::endl;
240 std::streambuf *sb=out.rdbuf();
242 size_t pstep=(width>>2)*6+px;
243 for (
size_t k=0; k<height && out.good(); k++)
245 for (
size_t i=0; i<width; i+=4)
250 for (
int j=0; j<12; j++)
252 sb->sputc(static_cast<char>(rgb[j]));
264 std::cerr <<
"storeBuffer(): Unknown pixel format: " 265 << GetPixelFormatName(static_cast<PfncFormat>(buffer->
getPixelFormat(part)))
267 return std::string();
273 std::cerr <<
"storeBuffer(): Received incomplete buffer" << std::endl;
274 return std::string();
278 std::cerr <<
"storeBuffer(): Received buffer without image" << std::endl;
279 return std::string();
293 std::string storeBufferAsDisparity(
const std::shared_ptr<GenApi::CNodeMapRef> &nodemap,
294 const std::shared_ptr<GenApi::CChunkAdapter> &chunkadapter,
297 std::string dispname;
310 inv=
static_cast<int>(
rcg::getFloat(nodemap,
"ChunkScan3dInvalidDataValue"));
313 double scale=
rcg::getFloat(nodemap,
"ChunkScan3dCoordinateScale");
314 double offset=
rcg::getFloat(nodemap,
"ChunkScan3dCoordinateOffset");
317 double u=
rcg::getFloat(nodemap,
"ChunkScan3dPrincipalPointU");
318 double v=
rcg::getFloat(nodemap,
"ChunkScan3dPrincipalPointV");
322 if (scale > 0 && f > 0 && t > 0)
331 name <<
"image_" << t_sec <<
"." << std::setfill(
'0') << std::setw(9) << t_nsec;
336 size_t width=buffer->
getWidth(part);
338 const unsigned char *p=
static_cast<const unsigned char *
>(buffer->
getBase(part))+
339 2*(width+px)*(height+1);
341 name <<
"_Disparity";
345 bool out1 = line_status & 0x01;
346 bool out2 = line_status & 0x02;
347 name <<
"_" << std::noboolalpha << out1 <<
"_" << out2;
349 dispname=name.
str()+
".pfm";
351 std::ofstream out(ensureNewName(dispname), std::ios::binary);
353 out <<
"Pf" << std::endl;
354 out << width <<
" " << height << std::endl;
357 std::streambuf *sb=out.rdbuf();
365 char *cc=
reinterpret_cast<char *
>(&pp);
366 msbfirst=(cc[0] != 1);
369 for (
size_t k=0; k<height && out.good(); k++)
372 for (
size_t i=0; i<width; i++)
377 val=(
static_cast<int>(p[0])<<8)|p[1];
381 val=(
static_cast<int>(p[1])<<8)|p[0];
386 float d=std::numeric_limits<float>::infinity();
389 d=
static_cast<float>(val*scale+offset);
392 char *c=
reinterpret_cast<char *
>(&d);
418 name <<
"_param.txt";
420 out.open(ensureNewName(name.
str()));
422 out <<
"# Created by gc_stream" << std::endl;
423 out << std::fixed << std::setprecision(5);
424 out <<
"camera.A=[" << f <<
" 0 " << u <<
"; 0 " << f <<
" " << v <<
"; 0 0 1]" << std::endl;
425 out <<
"camera.height=" << height << std::endl;
426 out <<
"camera.width=" << width << std::endl;
427 out <<
"rho=" << f*t << std::endl;
428 out <<
"t=" << t << std::endl;
440 std::atomic<bool> user_interrupt(
false);
442 void interruptHandler(
int)
444 std::cout <<
"Stopping ..." << std::endl;
451 void checkUserInterrupt()
456 std::cout <<
"Stopping ..." << std::endl;
465 int main(
int argc,
char *argv[])
469 signal(SIGINT, interruptHandler);
478 if (std::string(argv[i]) ==
"-t")
485 if (i < argc && std::string(argv[i]) !=
"-h")
494 std::shared_ptr<GenApi::CNodeMapRef> nodemap=dev->getRemoteNodeMap();
499 std::shared_ptr<GenApi::CChunkAdapter> chunkadapter=
rcg::getChunkAdapter(nodemap, dev->getTLType());
508 std::string key=argv[i++];
511 size_t k=key.find(
'=');
512 if (k != std::string::npos)
514 value=key.substr(k+1);
515 key=key.substr(0, k);
520 n=std::max(1, std::stoi(value));
524 if (value.size() > 0)
538 std::vector<std::string> component;
540 rcg::getEnum(nodemap,
"ComponentSelector", component,
false);
542 if (component.size() > 0)
544 std::cout << std::endl;
545 std::cout <<
"Available components (1 means enabled, 0 means disabled):" << std::endl;
546 std::cout << std::endl;
548 for (
size_t k=0; k<component.size(); k++)
550 rcg::setEnum(nodemap,
"ComponentSelector", component[k].c_str(),
true);
552 std::cout << component[k] <<
": ";
554 std::cout << std::endl;
557 std::cout << std::endl;
563 std::vector<std::shared_ptr<rcg::Stream> > stream=dev->getStreams();
565 if (stream.size() > 0)
569 std::thread thread_cui(checkUserInterrupt);
576 stream[0]->startStreaming();
578 std::cout <<
"Package size: " <<
rcg::getString(nodemap,
"GevSCPSPacketSize") << std::endl;
581 std::cout <<
"Press 'Enter' to abort grabbing." << std::endl;
583 std::cout << std::endl;
585 int buffers_received=0;
586 int buffers_incomplete=0;
587 auto time_start=std::chrono::steady_clock::now();
590 for (
int k=0; k<n && !user_interrupt; k++)
595 while (retry > 0 && !user_interrupt)
609 chunkadapter->AttachBuffer(
619 for (uint32_t part=0; part<npart; part++)
631 if (component ==
"Disparity")
633 name=storeBufferAsDisparity(nodemap, chunkadapter, buffer, part);
638 if (name.size() == 0)
640 name=storeBuffer(nodemap, chunkadapter, component, buffer, part);
647 std::cout <<
"Image '" << name <<
"' stored" << std::endl;
660 std::cout <<
"Received buffer with timestamp: " << t_sec <<
"." 661 << std::setfill(
'0') << std::setw(9) << t_nsec << std::endl;
666 auto current=std::chrono::system_clock::now();
668 static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(current.time_since_epoch()).count())-
674 if (chunkadapter) chunkadapter->DetachBuffer();
678 std::cerr <<
"Incomplete buffer received" << std::endl;
679 buffers_incomplete++;
684 std::cerr <<
"Cannot grab images" << std::endl;
692 stream[0]->stopStreaming();
697 std::cout << std::endl;
698 std::cout <<
"Received buffers: " << buffers_received << std::endl;
699 std::cout <<
"Incomplete buffers: " << buffers_incomplete << std::endl;
701 auto time_stop=std::chrono::steady_clock::now();
702 std::cout <<
"Buffers per second: " << std::setprecision(3)
703 << 1000.0*buffers_received/std::chrono::duration_cast<std::chrono::milliseconds>(time_stop-time_start).count()
708 if (buffers_received-buffers_incomplete > 0)
710 latency_ns/=buffers_received-buffers_incomplete;
713 std::cout <<
"Mean latency: " << std::setprecision(5) << latency_ns/1.0e6
714 <<
" ms (only meaningful if camera is synchronized e.g. via PTP!)" << std::endl;
719 if (buffers_incomplete == buffers_received)
726 std::cerr <<
"No streams available" << std::endl;
734 std::cerr <<
"Device '" << argv[1] <<
"' not found!" << std::endl;
742 std::cout << argv[0] <<
" -h | [-t] [<interface-id>:]<device-id> [n=<n>] [<key>=<value>] ..." << std::endl;
743 std::cout << std::endl;
744 std::cout <<
"Stores images from the specified device after applying the given optional GenICam parameters." << std::endl;
745 std::cout << std::endl;
746 std::cout <<
"Options:" << std::endl;
747 std::cout <<
"-h Prints help information and exits" << std::endl;
748 std::cout <<
"-t Testmode, which does not store images and provides extended statistics" << std::endl;
749 std::cout << std::endl;
750 std::cout <<
"Parameters:" << std::endl;
751 std::cout <<
"<interface-id> Optional GenICam ID of interface for connecting to the device" << std::endl;
752 std::cout <<
"<device-id> GenICam device ID, serial number or user defined name of device" << std::endl;
753 std::cout <<
"n=<n> Optional number of images to be received (default is 1)" << std::endl;
754 std::cout <<
"<key>=<value> Optional GenICam parameters to be changed in the given order" << std::endl;
756 std::cout << std::endl;
757 std::cout <<
"Streaming can be aborted by hitting the 'Enter' key." << std::endl;
762 catch (
const std::exception &ex)
764 std::cerr <<
"Exception: " << ex.what() << std::endl;
769 std::cerr <<
"Exception: " << ex.
what() << std::endl;
774 std::cerr <<
"Unknown exception!" << std::endl;
bool getBoolean(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception, bool igncache)
Get the value of a boolean feature of the given nodemap.
std::shared_ptr< Device > getDevice(const char *id)
Searches across all transport layers and interfaces for a device.
size_t getSizeFilled() const
Returns the number of bytes written into the buffer last time it has been filled. ...
std::shared_ptr< GenApi::CChunkAdapter > getChunkAdapter(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const std::string &tltype)
Sets ChunkModeActive to 1, creates a chunk adapter for the specified transport layer and attaches it ...
int main(int argc, char *argv[])
size_t getXPadding(std::uint32_t part) const
Returns horizontal padding of the data in the buffer in bytes.
int64_t getInteger(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, int64_t *vmin, int64_t *vmax, bool exception, bool igncache)
Get the value of an integer feature of the given nodemap.
size_t getWidth(std::uint32_t part) const
Returns the width of the image in pixel.
bool setEnum(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of an enumeration of the given nodemap.
static void clearSystems()
Clears the internal list of systems.
void convYCbCr411toQuadRGB(uint8_t rgb[12], const uint8_t *row, int i)
Conversion of a group of four pixels from YCbCr411 format (6 bytes for four pixels) to RGB...
The buffer class encapsulates a Genicam buffer that is provided by a stream.
void * getGlobalBase() const
Returns the global base address of the buffer memory.
void * getBase(std::uint32_t part) const
Returns the base address of the specified part of the multi-part buffer.
std::string getEnum(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Get the value of an enumeration of the given nodemap.
uint64_t getPixelFormat(std::uint32_t part) const
Returns the pixel format of the specified part as defined in the PFNC.
bool setString(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, const char *value, bool exception)
Set the value of a feature of the given nodemap.
double getFloat(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, double *vmin, double *vmax, bool exception, bool igncache)
Get the value of a double feature of the given nodemap.
uint64_t getTimestampNS() const
Returns the acquisition timestamp of the data in this buffer in ns.
bool isBigEndian() const
Returns if the data is given as big or little endian.
bool callCommand(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception)
Calls the given command.
bool getImagePresent(std::uint32_t part) const
Returns if a 2D, 3D or confidence image is present in the specified part.
bool getIsIncomplete() const
Signals if the buffer is incomplete due to an error.
GenICam's exception class.
size_t getHeight(std::uint32_t part) const
Returns the height of the image in pixel.
std::string getString(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const char *name, bool exception, bool igncache)
Get the value of a feature of the given nodemap.
std::string getComponetOfPart(const std::shared_ptr< GenApi::CNodeMapRef > &nodemap, const rcg::Buffer *buffer, uint32_t ipart)
virtual const char * what() const
Get error description (overwrite from std:exception)
std::uint32_t getNumberOfParts() const
Returns the number of parts, excluding chunk data.