40 #ifndef PCL_IO_PCD_IO_IMPL_H_
41 #define PCL_IO_PCD_IO_IMPL_H_
47 #include <boost/algorithm/string.hpp>
52 # ifndef WIN32_LEAN_AND_MEAN
53 # define WIN32_LEAN_AND_MEAN
54 # endif WIN32_LEAN_AND_MEAN
59 # define pcl_open _open
60 # define pcl_close(fd) _close(fd)
61 # define pcl_lseek(fd,offset,origin) _lseek(fd,offset,origin)
63 # include <sys/mman.h>
64 # define pcl_open open
65 # define pcl_close(fd) close(fd)
66 # define pcl_lseek(fd,offset,origin) lseek(fd,offset,origin)
72 template <
typename Po
intT> std::string
75 std::ostringstream oss;
76 oss.imbue (std::locale::classic ());
78 oss <<
"# .PCD v0.7 - Point Cloud Data file format"
82 std::vector<sensor_msgs::PointField> fields;
85 std::stringstream field_names, field_types, field_sizes, field_counts;
86 for (
size_t i = 0; i < fields.size (); ++i)
88 if (fields[i].name ==
"_")
91 field_names <<
" " << fields[i].name;
94 int count = abs (static_cast<int> (fields[i].count));
95 if (count == 0) count = 1;
96 field_counts <<
" " << count;
98 oss << field_names.str ();
99 oss <<
"\nSIZE" << field_sizes.str ()
100 <<
"\nTYPE" << field_types.str ()
101 <<
"\nCOUNT" << field_counts.str ();
103 if (nr_points != std::numeric_limits<int>::max ())
104 oss <<
"\nWIDTH " << nr_points <<
"\nHEIGHT " << 1 <<
"\n";
106 oss <<
"\nWIDTH " << cloud.
width <<
"\nHEIGHT " << cloud.
height <<
"\n";
115 if (nr_points != std::numeric_limits<int>::max ())
116 oss <<
"POINTS " << nr_points <<
"\n";
118 oss <<
"POINTS " << cloud.
points.size () <<
"\n";
124 template <
typename Po
intT>
int
130 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Input point cloud has no data!");
134 std::ostringstream oss;
135 oss << generateHeader<PointT> (cloud) <<
"DATA binary\n";
137 data_idx =
static_cast<int> (oss.tellp ());
140 HANDLE h_native_file = CreateFileA (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
141 if(h_native_file == INVALID_HANDLE_VALUE)
143 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during CreateFile!");
147 int fd =
pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC,
static_cast<mode_t
> (0600));
150 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during open!");
155 std::vector<sensor_msgs::PointField> fields;
156 std::vector<int> fields_sizes;
158 size_t data_size = 0;
162 for (
size_t i = 0; i < fields.size (); ++i)
164 if (fields[i].name ==
"_")
167 int fs = fields[i].count *
getFieldSize (fields[i].datatype);
169 fields_sizes.push_back (fs);
170 fields[nri++] = fields[i];
174 data_size = cloud.
points.size () * fsize;
178 HANDLE fm = CreateFileMappingA (h_native_file, NULL, PAGE_READWRITE, 0, (DWORD) (data_idx + data_size), NULL);
179 char *map =
static_cast<char*
>(MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, data_idx + data_size));
184 int result =
static_cast<int> (
pcl_lseek (fd, getpagesize () + data_size - 1, SEEK_SET));
188 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during lseek ()!");
192 result =
static_cast<int> (::write (fd,
"", 1));
196 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during write ()!");
200 char *map =
static_cast<char*
> (mmap (0, data_idx + data_size, PROT_WRITE, MAP_SHARED, fd, 0));
201 if (map == reinterpret_cast<char*> (-1))
204 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during mmap ()!");
210 memcpy (&map[0], oss.str ().c_str (), data_idx);
213 char *out = &map[0] + data_idx;
214 for (
size_t i = 0; i < cloud.
points.size (); ++i)
217 for (
size_t j = 0; j < fields.size (); ++j)
219 memcpy (out, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[j].offset, fields_sizes[nrj]);
220 out += fields_sizes[nrj++];
226 if (map_synchronization_)
227 msync (map, data_idx + data_size, MS_SYNC);
232 UnmapViewOfFile (map);
234 if (munmap (map, (data_idx + data_size)) == -1)
237 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during munmap ()!");
243 CloseHandle (h_native_file);
251 template <
typename Po
intT>
int
255 if (cloud.
points.empty ())
257 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!");
261 std::ostringstream oss;
262 oss << generateHeader<PointT> (cloud) <<
"DATA binary_compressed\n";
264 data_idx =
static_cast<int> (oss.tellp ());
267 HANDLE h_native_file = CreateFileA (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
268 if(h_native_file == INVALID_HANDLE_VALUE)
270 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during CreateFile!");
274 int fd =
pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC,
static_cast<mode_t
> (0600));
277 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during open!");
282 std::vector<sensor_msgs::PointField> fields;
284 size_t data_size = 0;
287 std::vector<int> fields_sizes (fields.size ());
289 for (
size_t i = 0; i < fields.size (); ++i)
291 if (fields[i].name ==
"_")
295 fsize += fields_sizes[nri];
296 fields[nri] = fields[i];
299 fields_sizes.resize (nri);
303 data_size = cloud.
points.size () * fsize;
310 char *only_valid_data =
static_cast<char*
> (malloc (data_size));
320 std::vector<char*> pters (fields.size ());
322 for (
size_t i = 0; i < pters.size (); ++i)
324 pters[i] = &only_valid_data[toff];
325 toff += fields_sizes[i] *
static_cast<int> (cloud.
points.size ());
329 for (
size_t i = 0; i < cloud.
points.size (); ++i)
331 for (
size_t j = 0; j < fields.size (); ++j)
333 memcpy (pters[j], reinterpret_cast<const char*> (&cloud.
points[i]) + fields[j].offset, fields_sizes[j]);
335 pters[j] += fields_sizes[j];
339 char* temp_buf =
static_cast<char*
> (malloc (static_cast<size_t> (static_cast<float> (data_size) * 1.5f + 8.0f)));
342 static_cast<uint32_t> (data_size),
344 static_cast<uint32_t> (static_cast<float>(data_size) * 1.5f));
345 unsigned int compressed_final_size = 0;
349 char *header = &temp_buf[0];
350 memcpy (&header[0], &compressed_size,
sizeof (
unsigned int));
351 memcpy (&header[4], &data_size,
sizeof (
unsigned int));
352 data_size = compressed_size + 8;
353 compressed_final_size =
static_cast<uint32_t
> (data_size) + data_idx;
360 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during compression!");
366 int result =
static_cast<int> (
pcl_lseek (fd, getpagesize () + data_size - 1, SEEK_SET));
370 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during lseek ()!");
374 result =
static_cast<int> (::write (fd,
"", 1));
378 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during write ()!");
385 HANDLE fm = CreateFileMapping (h_native_file, NULL, PAGE_READWRITE, 0, compressed_final_size, NULL);
386 char *map =
static_cast<char*
>(MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, compressed_final_size));
390 char *map =
static_cast<char*
> (mmap (0, compressed_final_size, PROT_WRITE, MAP_SHARED, fd, 0));
391 if (map == reinterpret_cast<char*> (-1))
394 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during mmap ()!");
400 memcpy (&map[0], oss.str ().c_str (), data_idx);
402 memcpy (&map[data_idx], temp_buf, data_size);
406 if (map_synchronization_)
407 msync (map, compressed_final_size, MS_SYNC);
412 UnmapViewOfFile (map);
414 if (munmap (map, (compressed_final_size)) == -1)
417 throw pcl::IOException (
"[pcl::PCDWriter::writeBinaryCompressed] Error during munmap ()!");
423 CloseHandle (h_native_file);
428 free (only_valid_data);
434 template <
typename Po
intT>
int
440 throw pcl::IOException (
"[pcl::PCDWriter::writeASCII] Input point cloud has no data!");
446 throw pcl::IOException (
"[pcl::PCDWriter::writeASCII] Number of points different than width * height!");
451 fs.open (file_name.c_str ());
453 if (!fs.is_open () || fs.fail ())
455 throw pcl::IOException (
"[pcl::PCDWriter::writeASCII] Could not open file for writing!");
459 fs.precision (precision);
460 fs.imbue (std::locale::classic ());
462 std::vector<sensor_msgs::PointField> fields;
466 fs << generateHeader<PointT> (cloud) <<
"DATA ascii\n";
468 std::ostringstream stream;
469 stream.precision (precision);
470 stream.imbue (std::locale::classic ());
472 for (
size_t i = 0; i < cloud.
points.size (); ++i)
474 for (
size_t d = 0; d < fields.size (); ++d)
477 if (fields[d].name ==
"_")
480 int count = fields[d].count;
484 for (
int c = 0; c < count; ++c)
486 switch (fields[d].datatype)
491 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (int8_t),
sizeof (int8_t));
495 stream << boost::numeric_cast<uint32_t>(value);
501 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (uint8_t),
sizeof (uint8_t));
505 stream << boost::numeric_cast<uint32_t>(value);
511 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (int16_t),
sizeof (int16_t));
515 stream << boost::numeric_cast<int16_t>(value);
521 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (uint16_t),
sizeof (uint16_t));
525 stream << boost::numeric_cast<uint16_t>(value);
531 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (int32_t),
sizeof (int32_t));
535 stream << boost::numeric_cast<int32_t>(value);
541 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (uint32_t),
sizeof (uint32_t));
545 stream << boost::numeric_cast<uint32_t>(value);
551 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (
float),
sizeof (
float));
555 stream << boost::numeric_cast<float>(value);
561 memcpy (&value, reinterpret_cast<const char*> (&cloud.
points[i]) + fields[d].offset + c * sizeof (
double),
sizeof (
double));
565 stream << boost::numeric_cast<double>(value);
569 PCL_WARN (
"[pcl::PCDWriter::writeASCII] Incorrect field data type specified (%d)!\n", fields[d].datatype);
573 if (d < fields.size () - 1 || c < static_cast<int> (fields[d].count - 1))
578 std::string result = stream.str ();
579 boost::trim (result);
581 fs << result <<
"\n";
589 template <
typename Po
intT>
int
592 const std::vector<int> &indices)
594 if (cloud.
points.empty () || indices.empty ())
596 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Input point cloud has no data or empty indices given!");
600 std::ostringstream oss;
601 oss << generateHeader<PointT> (cloud,
static_cast<int> (indices.size ())) <<
"DATA binary\n";
603 data_idx =
static_cast<int> (oss.tellp ());
606 HANDLE h_native_file = CreateFileA (file_name.c_str (), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
607 if(h_native_file == INVALID_HANDLE_VALUE)
609 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during CreateFile!");
613 int fd =
pcl_open (file_name.c_str (), O_RDWR | O_CREAT | O_TRUNC,
static_cast<mode_t
> (0600));
616 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during open!");
621 std::vector<sensor_msgs::PointField> fields;
622 std::vector<int> fields_sizes;
624 size_t data_size = 0;
628 for (
size_t i = 0; i < fields.size (); ++i)
630 if (fields[i].name ==
"_")
633 int fs = fields[i].count *
getFieldSize (fields[i].datatype);
635 fields_sizes.push_back (fs);
636 fields[nri++] = fields[i];
640 data_size = indices.size () * fsize;
644 HANDLE fm = CreateFileMapping (h_native_file, NULL, PAGE_READWRITE, 0, data_idx + data_size, NULL);
645 char *map =
static_cast<char*
>(MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, data_idx + data_size));
650 int result =
static_cast<int> (
pcl_lseek (fd, getpagesize () + data_size - 1, SEEK_SET));
654 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during lseek ()!");
658 result =
static_cast<int> (::write (fd,
"", 1));
662 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during write ()!");
666 char *map =
static_cast<char*
> (mmap (0, data_idx + data_size, PROT_WRITE, MAP_SHARED, fd, 0));
667 if (map == reinterpret_cast<char*> (-1))
670 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during mmap ()!");
676 memcpy (&map[0], oss.str ().c_str (), data_idx);
678 char *out = &map[0] + data_idx;
680 for (
size_t i = 0; i < indices.size (); ++i)
683 for (
size_t j = 0; j < fields.size (); ++j)
685 memcpy (out, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[j].offset, fields_sizes[nrj]);
686 out += fields_sizes[nrj++];
692 if (map_synchronization_)
693 msync (map, data_idx + data_size, MS_SYNC);
698 UnmapViewOfFile (map);
700 if (munmap (map, (data_idx + data_size)) == -1)
703 throw pcl::IOException (
"[pcl::PCDWriter::writeBinary] Error during munmap ()!");
709 CloseHandle(h_native_file);
717 template <
typename Po
intT>
int
720 const std::vector<int> &indices,
723 if (cloud.
points.empty () || indices.empty ())
725 throw pcl::IOException (
"[pcl::PCDWriter::writeASCII] Input point cloud has no data or empty indices given!");
731 throw pcl::IOException (
"[pcl::PCDWriter::writeASCII] Number of points different than width * height!");
736 fs.open (file_name.c_str ());
737 if (!fs.is_open () || fs.fail ())
739 throw pcl::IOException (
"[pcl::PCDWriter::writeASCII] Could not open file for writing!");
742 fs.precision (precision);
743 fs.imbue (std::locale::classic ());
745 std::vector<sensor_msgs::PointField> fields;
749 fs << generateHeader<PointT> (cloud,
static_cast<int> (indices.size ())) <<
"DATA ascii\n";
751 std::ostringstream stream;
752 stream.precision (precision);
753 stream.imbue (std::locale::classic ());
756 for (
size_t i = 0; i < indices.size (); ++i)
758 for (
size_t d = 0; d < fields.size (); ++d)
761 if (fields[d].name ==
"_")
764 int count = fields[d].count;
768 for (
int c = 0; c < count; ++c)
770 switch (fields[d].datatype)
775 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (int8_t),
sizeof (int8_t));
779 stream << boost::numeric_cast<uint32_t>(value);
785 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (uint8_t),
sizeof (uint8_t));
789 stream << boost::numeric_cast<uint32_t>(value);
795 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (int16_t),
sizeof (int16_t));
799 stream << boost::numeric_cast<int16_t>(value);
805 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (uint16_t),
sizeof (uint16_t));
809 stream << boost::numeric_cast<uint16_t>(value);
815 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (int32_t),
sizeof (int32_t));
819 stream << boost::numeric_cast<int32_t>(value);
825 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (uint32_t),
sizeof (uint32_t));
829 stream << boost::numeric_cast<uint32_t>(value);
835 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (
float),
sizeof (
float));
839 stream << boost::numeric_cast<float>(value);
845 memcpy (&value, reinterpret_cast<const char*> (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (
double),
sizeof (
double));
849 stream << boost::numeric_cast<double>(value);
853 PCL_WARN (
"[pcl::PCDWriter::writeASCII] Incorrect field data type specified (%d)!\n", fields[d].datatype);
857 if (d < fields.size () - 1 || c < static_cast<int> (fields[d].count - 1))
862 std::string result = stream.str ();
863 boost::trim (result);
865 fs << result <<
"\n";
871 #endif //#ifndef PCL_IO_PCD_IO_H_