Skip to content

Commit ed1bdb3

Browse files
Fixes PLY parsing of char and uchar scalars
WIP of #1381. int8 and uint8 types were being evaluated as char and unsigned char, their actual original type, so whenever a lexical_cast was performed from a multi-digit string to an (unsigned) char, a bad_lexical_cast exception was thrown and the value set to a quiet NaN. Functionally-wise, this PR will make color parsing work.
1 parent bf51cf4 commit ed1bdb3

File tree

4 files changed

+207
-20
lines changed

4 files changed

+207
-20
lines changed

io/include/pcl/io/ply/ply.h

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,23 +73,25 @@ namespace pcl
7373
# error
7474
#endif
7575

76-
#define PLY_TYPE_TRAITS(TYPE, NAME, OLD_NAME) \
76+
#define PLY_TYPE_TRAITS(TYPE, PARSE_TYPE, NAME, OLD_NAME) \
7777
template <> \
7878
struct type_traits<TYPE> \
7979
{ \
8080
typedef TYPE type; \
81-
static const char* name() { return NAME; } \
82-
static const char* old_name() { return OLD_NAME; } \
83-
}
81+
typedef PARSE_TYPE parse_type; \
82+
static const char* name () { return NAME; } \
83+
static const char* old_name () { return OLD_NAME; } \
84+
};
85+
86+
PLY_TYPE_TRAITS(int8, int16, "int8", "char");
87+
PLY_TYPE_TRAITS(int16, int16, "int16", "short");
88+
PLY_TYPE_TRAITS(int32, int32, "int32", "int");
89+
PLY_TYPE_TRAITS(uint8, uint16, "uint8", "uchar");
90+
PLY_TYPE_TRAITS(uint16, uint16, "uint16", "ushort");
91+
PLY_TYPE_TRAITS(uint32, uint32, "uint32", "uint");
92+
PLY_TYPE_TRAITS(float32, float32, "float32", "float");
93+
PLY_TYPE_TRAITS(float64, float64, "float64", "double");
8494

85-
PLY_TYPE_TRAITS(int8, "int8", "char");
86-
PLY_TYPE_TRAITS(int16, "int16", "short");
87-
PLY_TYPE_TRAITS(int32, "int32", "int");
88-
PLY_TYPE_TRAITS(uint8, "uint8", "uchar");
89-
PLY_TYPE_TRAITS(uint16, "uint16", "ushort");
90-
PLY_TYPE_TRAITS(uint32, "uint32", "uint");
91-
PLY_TYPE_TRAITS(float32, "float32", "float");
92-
PLY_TYPE_TRAITS(float64, "float64", "double");
9395

9496
#undef PLY_TYPE_TRAITS
9597

io/include/pcl/io/ply/ply_parser.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ inline bool pcl::io::ply::ply_parser::parse_scalar_property (format_type format,
565565
istream >> value_s;
566566
try
567567
{
568-
value = boost::lexical_cast<scalar_type> (value_s);
568+
value = static_cast<scalar_type> (boost::lexical_cast<typename pcl::io::ply::type_traits<scalar_type>::parse_type> (value_s));
569569
}
570570
catch (boost::bad_lexical_cast &)
571571
{
@@ -641,7 +641,7 @@ inline bool pcl::io::ply::ply_parser::parse_list_property (format_type format, s
641641
istream >> value_s;
642642
try
643643
{
644-
value = boost::lexical_cast<scalar_type> (value_s);
644+
value = static_cast<scalar_type> (boost::lexical_cast<typename pcl::io::ply::type_traits<scalar_type>::parse_type> (value_s));
645645
}
646646
catch (boost::bad_lexical_cast &)
647647
{

test/io/CMakeLists.txt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
if(WITH_OPENNI)
2-
PCL_ADD_TEST(io_io test_io
3-
FILES test_io.cpp
4-
LINK_WITH pcl_gtest pcl_io)
5-
endif()
1+
PCL_ADD_TEST(io_io test_io
2+
FILES test_io.cpp
3+
LINK_WITH pcl_gtest pcl_io)
4+
65
PCL_ADD_TEST(io_iterators test_iterators
76
FILES test_iterators.cpp
87
LINK_WITH pcl_gtest pcl_io)

test/io/test_io.cpp

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,6 @@ TEST (PCL, PCDReaderWriterASCIIColorPrecision)
761761
}
762762
}
763763

764-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
765764
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
766765
TEST (PCL, ASCIIReader)
767766
{
@@ -865,6 +864,193 @@ TEST (PCL, PLYReaderWriter)
865864
}
866865
}
867866

867+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
868+
class PLYTest : public ::testing::Test
869+
{
870+
protected:
871+
872+
PLYTest () : mesh_file_ply_("ply_color_mesh.ply")
873+
{
874+
std::ofstream fs;
875+
fs.open (mesh_file_ply_);
876+
fs << "ply\n"
877+
"format ascii 1.0\n"
878+
"element vertex 4\n"
879+
"property float x\n"
880+
"property float y\n"
881+
"property float z\n"
882+
"property uchar red\n"
883+
"property uchar green\n"
884+
"property uchar blue\n"
885+
"property uchar alpha\n"
886+
"element face 2\n"
887+
"property list uchar int vertex_indices\n"
888+
"end_header\n"
889+
"4.23607 0 1.61803 255 0 0 255\n"
890+
"2.61803 2.61803 2.61803 0 255 0 0\n"
891+
"0 1.61803 4.23607 0 0 255 128\n"
892+
"0 -1.61803 4.23607 255 255 255 128\n"
893+
"3 0 1 2\n"
894+
"3 1 2 3\n";
895+
fs.close ();
896+
}
897+
898+
virtual
899+
~PLYTest () { remove (mesh_file_ply_.c_str ()); }
900+
901+
std::string mesh_file_ply_;
902+
};
903+
904+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
905+
TEST_F (PLYTest, LoadPLYFileColoredASCII)
906+
{
907+
int res;
908+
uint32_t rgba, rgba_1, rgba_2, rgba_3, rgba_4;
909+
910+
// Test colors from ply_benchmark.ply
911+
rgba_1 = static_cast<uint32_t> (255) << 24 | static_cast<uint32_t> (255) << 16 |
912+
static_cast<uint32_t> (0) << 8 | static_cast<uint32_t> (0);
913+
rgba_2 = static_cast<uint32_t> (0) << 24 | static_cast<uint32_t> (0) << 16 |
914+
static_cast<uint32_t> (255) << 8 | static_cast<uint32_t> (0);
915+
rgba_3 = static_cast<uint32_t> (128) << 24 | static_cast<uint32_t> (0) << 16 |
916+
static_cast<uint32_t> (0) << 8 | static_cast<uint32_t> (255);
917+
rgba_4 = static_cast<uint32_t> (128) << 24 | static_cast<uint32_t> (255) << 16 |
918+
static_cast<uint32_t> (255) << 8 | static_cast<uint32_t> (255);
919+
920+
// Blobs
921+
{
922+
PCLPointCloud2 cloud_blob;
923+
uint32_t ps;
924+
int32_t offset = -1;
925+
926+
// check if loading is ok
927+
res = loadPLYFile (mesh_file_ply_, cloud_blob);
928+
ASSERT_EQ (res, 0);
929+
930+
// blob has proper structure
931+
EXPECT_EQ (cloud_blob.height, 1);
932+
EXPECT_EQ (cloud_blob.width, 4);
933+
EXPECT_EQ (cloud_blob.fields.size(), 4);
934+
EXPECT_FALSE (cloud_blob.is_bigendian);
935+
EXPECT_EQ (cloud_blob.point_step, 16);
936+
EXPECT_EQ (cloud_blob.row_step, 16 * 4);
937+
EXPECT_EQ (cloud_blob.data.size(), 16 * 4);
938+
// EXPECT_TRUE (cloud_blob.is_dense); // this is failing and it shouldnt?
939+
940+
// scope blob data
941+
ps = cloud_blob.point_step;
942+
for (size_t i = 0; i < cloud_blob.fields.size (); ++i)
943+
if (cloud_blob.fields[i].name == std::string("rgba"))
944+
offset = static_cast<int32_t> (cloud_blob.fields[i].offset);
945+
946+
ASSERT_GE (offset, 0);
947+
948+
// 1st point
949+
rgba = *reinterpret_cast<uint32_t *> (&cloud_blob.data[offset]);
950+
ASSERT_EQ (rgba, rgba_1);
951+
952+
// 2th point
953+
rgba = *reinterpret_cast<uint32_t *> (&cloud_blob.data[ps + offset]);
954+
ASSERT_EQ (rgba, rgba_2);
955+
956+
// 3th point
957+
rgba = *reinterpret_cast<uint32_t *> (&cloud_blob.data[2 * ps + offset]);
958+
ASSERT_EQ (rgba, rgba_3);
959+
960+
// 4th point
961+
rgba = *reinterpret_cast<uint32_t *> (&cloud_blob.data[3 * ps + offset]);
962+
ASSERT_EQ (rgba, rgba_4);
963+
}
964+
965+
// PointCloud<PointXYZRGB>
966+
{
967+
PointCloud<PointXYZRGB> cloud_rgb;
968+
969+
// check if loading is ok
970+
res = loadPLYFile (mesh_file_ply_, cloud_rgb);
971+
ASSERT_EQ (res, 0);
972+
973+
// cloud has proper structure
974+
EXPECT_EQ (cloud_rgb.height, 1);
975+
EXPECT_EQ (cloud_rgb.width, 4);
976+
EXPECT_EQ (cloud_rgb.points.size(), 4);
977+
// EXPECT_TRUE (cloud_rgb.is_dense); // this is failing and it shouldnt?
978+
979+
// scope cloud data
980+
ASSERT_EQ (cloud_rgb[0].rgba, rgba_1);
981+
ASSERT_EQ (cloud_rgb[1].rgba, rgba_2);
982+
ASSERT_EQ (cloud_rgb[2].rgba, rgba_3);
983+
ASSERT_EQ (cloud_rgb[3].rgba, rgba_4);
984+
}
985+
986+
//PointCloud<PointXYZRGBA>
987+
{
988+
PointCloud<PointXYZRGBA> cloud_rgba;
989+
990+
// check if loading is ok
991+
res = loadPLYFile (mesh_file_ply_, cloud_rgba);
992+
ASSERT_EQ (res, 0);
993+
994+
// cloud has proper structure
995+
EXPECT_EQ (cloud_rgba.height, 1);
996+
EXPECT_EQ (cloud_rgba.width, 4);
997+
EXPECT_EQ (cloud_rgba.points.size(), 4);
998+
// EXPECT_TRUE (cloud_rgba.is_dense); // this is failing and it shouldnt?
999+
1000+
// scope cloud data
1001+
ASSERT_EQ (cloud_rgba[0].rgba, rgba_1);
1002+
ASSERT_EQ (cloud_rgba[1].rgba, rgba_2);
1003+
ASSERT_EQ (cloud_rgba[2].rgba, rgba_3);
1004+
ASSERT_EQ (cloud_rgba[3].rgba, rgba_4);
1005+
}
1006+
1007+
//PolygonMesh
1008+
{
1009+
PolygonMesh mesh;
1010+
1011+
uint32_t ps;
1012+
int32_t offset = -1;
1013+
1014+
// check if loading is ok
1015+
res = loadPLYFile (mesh_file_ply_, mesh);
1016+
ASSERT_EQ (res, 0);
1017+
1018+
// blob has proper structure
1019+
EXPECT_EQ (mesh.cloud.height, 1);
1020+
EXPECT_EQ (mesh.cloud.width, 4);
1021+
EXPECT_EQ (mesh.cloud.fields.size(), 4);
1022+
EXPECT_FALSE (mesh.cloud.is_bigendian);
1023+
EXPECT_EQ (mesh.cloud.point_step, 16);
1024+
EXPECT_EQ (mesh.cloud.row_step, 16 * 4);
1025+
EXPECT_EQ (mesh.cloud.data.size(), 16 * 4);
1026+
// EXPECT_TRUE (mesh.cloud.is_dense); // this is failing and it shouldnt?
1027+
1028+
// scope blob data
1029+
ps = mesh.cloud.point_step;
1030+
for (size_t i = 0; i < mesh.cloud.fields.size (); ++i)
1031+
if (mesh.cloud.fields[i].name == std::string("rgba"))
1032+
offset = static_cast<int32_t> (mesh.cloud.fields[i].offset);
1033+
1034+
ASSERT_GE (offset, 0);
1035+
1036+
// 1st point
1037+
rgba = *reinterpret_cast<uint32_t *> (&mesh.cloud.data[offset]);
1038+
ASSERT_EQ (rgba, rgba_1);
1039+
1040+
// 2th point
1041+
rgba = *reinterpret_cast<uint32_t *> (&mesh.cloud.data[ps + offset]);
1042+
ASSERT_EQ (rgba, rgba_2);
1043+
1044+
// 3th point
1045+
rgba = *reinterpret_cast<uint32_t *> (&mesh.cloud.data[2 * ps + offset]);
1046+
ASSERT_EQ (rgba, rgba_3);
1047+
1048+
// 4th point
1049+
rgba = *reinterpret_cast<uint32_t *> (&mesh.cloud.data[3 * ps + offset]);
1050+
ASSERT_EQ (rgba, rgba_4);
1051+
}
1052+
}
1053+
8681054
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8691055

8701056
struct PointXYZFPFH33

0 commit comments

Comments
 (0)