Skip to content
Snippets Groups Projects
Commit 04c0573e authored by Bastien Montagne's avatar Bastien Montagne
Browse files

Fix T78278: Cannot import some binary PLY file generated by Rhinos3D 6.0

Issue was that in binary file reading, python only recognize `'\n'`
character as line separator... PLY seems to allow (or at least, use)
other OS-related variants of lines terminators, so we have to implement
our own line iterator for those cases...
parent 919541ff
Branches
Tags
No related merge requests found
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
bl_info = { bl_info = {
"name": "Stanford PLY format", "name": "Stanford PLY format",
"author": "Bruce Merry, Campbell Barton", "author": "Bruce Merry, Campbell Barton", "Bastien Montagne"
"version": (2, 0, 0), "version": (2, 1, 0),
"blender": (2, 90, 0), "blender": (2, 90, 0),
"location": "File > Import/Export", "location": "File > Import/Export",
"description": "Import-Export PLY mesh data with UVs and vertex colors", "description": "Import-Export PLY mesh data with UVs and vertex colors",
......
...@@ -152,14 +152,45 @@ def read(filepath): ...@@ -152,14 +152,45 @@ def read(filepath):
invalid_ply = (None, None, None) invalid_ply = (None, None, None)
with open(filepath, 'rb') as plyf: with open(filepath, 'rb') as plyf:
signature = plyf.readline() signature = plyf.peek(5)
if not signature.startswith(b'ply'): if not signature.startswith(b'ply') or not len(signature) >= 5:
print("Signature line was invalid") print("Signature line was invalid")
return invalid_ply return invalid_ply
custom_line_sep = None
if signature[3] != ord(b'\n'):
if signature[3] != ord(b'\r'):
print("Unknown line separator")
return invalid_ply
if signature[4] == ord(b'\n'):
custom_line_sep = b"\r\n"
else:
custom_line_sep = b"\r"
# Work around binary file reading only accepting "\n" as line separator.
plyf_header_line_iterator = lambda plyf: plyf
if custom_line_sep is not None:
def _plyf_header_line_iterator(plyf):
buff = plyf.peek(2**16)
while len(buff) != 0:
read_bytes = 0
buff = buff.split(custom_line_sep)
for line in buff[:-1]:
read_bytes += len(line) + len(custom_line_sep)
if line.startswith(b'end_header'):
# Since reader code might (will) break iteration at this point,
# we have to ensure file is read up to here, yield, amd return...
plyf.read(read_bytes)
yield line
return
yield line
plyf.read(read_bytes)
buff = buff[-1] + plyf.peek(2**16)
plyf_header_line_iterator = _plyf_header_line_iterator
valid_header = False valid_header = False
for line in plyf: for line in plyf_header_line_iterator(plyf):
tokens = re.split(br'[ \r\n]+', line) tokens = re.split(br'[ \r\n]+', line)
if len(tokens) == 0: if len(tokens) == 0:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment