[Bf-extensions-cvs] [5b85e3e] master: io_points_pcd - import binary compressed .pcd files. failed lzf and call to external pcl tool.

Aurel Wildfellner noreply at git.blender.org
Thu Jan 7 18:28:53 CET 2016


Commit: 5b85e3e8ad042aab31b71d191eb5599224aaf018
Author: Aurel Wildfellner
Date:   Thu Jan 7 18:27:47 2016 +0100
Branches: master
https://developer.blender.org/rBAC5b85e3e8ad042aab31b71d191eb5599224aaf018

io_points_pcd - import binary compressed .pcd files. failed lzf and call to external pcl tool.

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

M	io_points_pcd/pcd_utils.py
M	io_points_pcd/pcdparser.py

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

diff --git a/io_points_pcd/pcd_utils.py b/io_points_pcd/pcd_utils.py
index f0f1bc9..c38a14f 100644
--- a/io_points_pcd/pcd_utils.py
+++ b/io_points_pcd/pcd_utils.py
@@ -18,6 +18,10 @@
 
 import bpy
 
+import os
+import subprocess
+import tempfile
+
 from . import pcdparser
 
 
@@ -42,6 +46,24 @@ def create_and_link_mesh(name, points):
 
 
 def import_pcd(filepath, name="new_pointcloud"):
+    # check if the file is binary compressed
+    parser = pcdparser.PCDParser.factory(filepath, pcdparser.PointXYZ)
+    parser.onlyParseHeader()
+    is_binary_compressed = parser.datatype == 'BINARY_COMPRESSED'
+
+    # create a temp uncompressed pcd file
+    if (is_binary_compressed):
+        tmpdir = tempfile.TemporaryDirectory()
+        tmpfilepath = tmpdir.name + "blender_pcd_io_tmp.pcd"
+        try:
+            subprocess.call(["pcl_convert_pcd_ascii_binary", filepath, tmpfilepath, "1"])
+        except FileNotFoundError:
+            print("[ERROR] Can't read BINARY COMPRESSED PCD. No pcl_convert_pcd_ascii_binary found! Have you installed libPCL?")
+            return
+        filepath = tmpfilepath
+
+
+    # do actual parsing
     parser = pcdparser.PCDParser.factory(filepath, pcdparser.PointXYZ)
     parser.parseFile()
     points = parser.getPoints()
diff --git a/io_points_pcd/pcdparser.py b/io_points_pcd/pcdparser.py
index 1836aad..269cf15 100644
--- a/io_points_pcd/pcdparser.py
+++ b/io_points_pcd/pcdparser.py
@@ -18,6 +18,20 @@
 
 
 import struct
+import io
+
+try:
+    import lzf
+    GOT_LZF_MODULE=True
+except:
+    GOT_LZF_MODULE=False
+
+
+
+def dumpHexData(data):
+    for byte in data:
+        print(hex(byte) + " ", end="")
+    print()
 
 
 def encodeASCIILine(line):
@@ -108,6 +122,10 @@ class PCDParser:
             self.parseHeader()
             self.parsePoints()
 
+    def onlyParseHeader(self):
+        with open(self.filepath, 'rb') as self.file:
+            self.parseHeader()
+
 
     def parseHeader(self):
         for b in self.file:
@@ -226,6 +244,8 @@ class PCDParser_v0_7(PCDParser):
             self.datatype = 'ASCII'
         elif split[0] == "binary":
             self.datatype = 'BINARY'
+        elif split[0] == "binary_compressed":
+            self.datatype = 'BINARY_COMPRESSED'
         self.headerEnd = True
 
 
@@ -239,6 +259,12 @@ class PCDParser_v0_7(PCDParser):
             self.parseASCII()
         elif self.datatype == 'BINARY':
             self.parseBINARY()
+        elif self.datatype == 'BINARY_COMPRESSED':
+            if not GOT_LZF_MODULE:
+                print("[ERROR] No support for BINARY COMPRESSED data format.")
+                return
+            else:
+                self.parseBINARY_COMPRESSED()
 
 
     def parseASCII(self):
@@ -279,7 +305,27 @@ class PCDParser_v0_7(PCDParser):
             self.points.append(point)
 
 
-    def parseBINARY(self):
+    def parseBINARY_COMPRESSED(self):
+        """ BROKEN!!! - There seem to be uncompatiblities 
+            with pcl LZF and liblzf"""
+        max_size = 1024**3 # 1GB 
+        fs = '<i'
+        compressed_len = struct.unpack('<i', self.file.read(4))[0]
+        decompressed_len = struct.unpack('<i', self.file.read(4))[0]
+
+        compressed_body = self.file.read(compressed_len)
+        decompressed_body = lzf.decompress(compressed_body, max_size)
+
+        fobj = io.BytesIO(decompressed_body)
+        self.parseBINARY(fobj)
+
+
+
+    def parseBINARY(self, infile=""):
+        
+        if infile == "":
+            infile = self.file
+
         for pointi in range(self.numPoints):
             point = self.PointClass()
 
@@ -313,7 +359,7 @@ class PCDParser_v0_7(PCDParser):
                         elif fieldsize == 4: #signed int
                             fs =  '<i'
 
-                    raw = self.file.read(fieldsize)
+                    raw = infile.read(fieldsize)
                     if (fs):
                         data = struct.unpack(fs, raw)
                         values.append(data[0])
@@ -361,8 +407,6 @@ class PCDWriter:
 
 
 
-
-
 def test():
     parser = PCDParser.factory('test.pcd', PointXYZ)
     if parser:



More information about the Bf-extensions-cvs mailing list