[Bf-extensions-cvs] [04c0573e] blender-v2.90-release: Fix T78278: Cannot import some binary PLY file generated by Rhinos3D 6.0

Bastien Montagne noreply at git.blender.org
Fri Aug 7 16:41:58 CEST 2020


Commit: 04c0573ee77cc955cf585a0d7a61163375eb57cd
Author: Bastien Montagne
Date:   Fri Aug 7 16:38:40 2020 +0200
Branches: blender-v2.90-release
https://developer.blender.org/rBA04c0573ee77cc955cf585a0d7a61163375eb57cd

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...

===================================================================

M	io_mesh_ply/__init__.py
M	io_mesh_ply/import_ply.py

===================================================================

diff --git a/io_mesh_ply/__init__.py b/io_mesh_ply/__init__.py
index 1a69c346..a3f08ebd 100644
--- a/io_mesh_ply/__init__.py
+++ b/io_mesh_ply/__init__.py
@@ -20,8 +20,8 @@
 
 bl_info = {
     "name": "Stanford PLY format",
-    "author": "Bruce Merry, Campbell Barton",
-    "version": (2, 0, 0),
+    "author": "Bruce Merry, Campbell Barton", "Bastien Montagne"
+    "version": (2, 1, 0),
     "blender": (2, 90, 0),
     "location": "File > Import/Export",
     "description": "Import-Export PLY mesh data with UVs and vertex colors",
diff --git a/io_mesh_ply/import_ply.py b/io_mesh_ply/import_ply.py
index c118aa3c..d9d12d67 100644
--- a/io_mesh_ply/import_ply.py
+++ b/io_mesh_ply/import_ply.py
@@ -152,14 +152,45 @@ def read(filepath):
     invalid_ply = (None, None, None)
 
     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")
             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
-        for line in plyf:
+        for line in plyf_header_line_iterator(plyf):
             tokens = re.split(br'[ \r\n]+', line)
 
             if len(tokens) == 0:



More information about the Bf-extensions-cvs mailing list