1

I am trying to stream a ply data using SetInputString() instead of reading it from a file. The data is a binary string, which looks like:

ply
format binary_little_endian 1.0
comment VTK generated PLY File
comment SPACE=LPS
obj_info vtkPolyData points and polygons: vtk4.0
element vertex 120
property float x
property float y
property float z
property float u
property float v
element face 120
property list uchar int vertex_indices
end_header
??B"?B??

If I read the same string from a file through reader->SetFileName(), it works as expected. But for the following case, the number of read cells are 0.

vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
reader->SetReadFromInputString(true);
reader->ReadFromInputStringOn();
reader->SetInputString(data.c_str());
reader->Update();

vtkSmartPointer<vtkPolyData> polyData = reader->GetOutput();
polyData->Modified();

std::cout << "data: " << data.c_str() <<std::endl;
std::cout << "number of cells: " << polyData->GetNumberOfCells() <<std::endl;
mystic.06
  • 189
  • 8

1 Answers1

0

The problem is that you used the incorrect method to set the input for vtkPLYReader (note that the relevant methods are actually from a base class of vtkPLYReader - vtkDataReader).

The function you used:

void vtkDataReader::SetInputString(const char * in); 

expects a null-terminated string for it's input parameter (const char * in).
As you can see in the link it is an array of chars terminated by an element with value 0.
This works well for text because there is no text character with value 0.
A binary buffer however may (and probably will if it is big enough) contain bytes with value 0.

Instead you should use one of the following:

void vtkDataReader::SetInputString(const char * in, int len);
// Or:
void vtkDataReader::SetBinaryInputString(const char* , int len);

At first I thought SetBinaryInputString is the only one that can handle a binary buffer, but as you can see in the documentation link below, both have actually the same description:

Specify the InputString for use when reading from a character array. Optionally include the length for binary strings. Note that a copy of the string is made and stored. If this causes exceedingly large memory consumption, consider using InputArray instead.

You can try both of them and verify you got the proper result.

Notes:

  1. If data is a std::string, make sure you initialize it with the proper constructor that accepts a count parameter and supports characters with value 0 (see here: Can a std::string contain embedded nulls?).
  2. Make sure that you pass the entrire length of the binary buffer in the len parameter. I mean that you shouldn't measure the length by using a function that assumes a null-termination like strlen. If it's indeed a std::string you can use std::string::length() safely.
  3. A binary buffer is not really a string. I prefer to keep such buffers in a std::vector<char>. You can use the data() and size() methods of std::vector to pass as agruments to SetInputString / SetBinaryInputString.

See documentation for vtkDataReader, which is the base class of vtkPLYReader and implements the methods mentioned above.

wohlstad
  • 12,661
  • 10
  • 26
  • 39