simplify thumbnail reading and remove some warnings
[blender.git] / release / freedesktop / blender-thumbnailer.py
index 5274da103b9ef33f3507f19df7ccfff0df5d38d8..27d6259d172075fc87a00d3e864ed7807346d959 100755 (executable)
@@ -25,57 +25,54 @@ To run automatically with nautilus:
    gconftool --type string --set /desktop/gnome/thumbnailers/application@x-blender/command "blender-thumbnailer.py %i %o"
 """
 
-import os
 import struct
-import sys
 
 def blend_extract_thumb(path):
+    import os
+
     # def MAKE_ID(tag): ord(tag[0])<<24 | ord(tag[1])<<16 | ord(tag[2])<<8 | ord(tag[3])
     REND = 1145980242 # MAKE_ID(b'REND')
     TEST = 1414743380 # MAKE_ID(b'TEST')
 
     blendfile = open(path, 'rb')
 
-    head = blendfile.read(7)
+    head = blendfile.read(12)
 
     if head[0:2] == b'\x1f\x8b': # gzip magic
         import gzip
         blendfile.close()
         blendfile = gzip.open(path, 'rb')
-        head = blendfile.read(7)
+        head = blendfile.read(12)
 
-    if head != b'BLENDER':
+    if not head.startswith(b'BLENDER'):
         blendfile.close()
         return None, 0, 0
 
-    is_64_bit = (blendfile.read(1) == b'-')
+    is_64_bit = (head[7] == b'-')
 
     # true for PPC, false for X86
-    is_big_endian = (blendfile.read(1) == b'V')
-
-    # Now read the bhead chunk!!!
-    blendfile.read(3) # skip the version
+    is_big_endian = (head[8] == b'V')
 
-    sizeof_pointer = 8 if is_64_bit else 4
+    # blender pre 2.5 had no thumbs
+    if head[9:11] <= b'24':
+        return None, 0, 0
 
     sizeof_bhead = 24 if is_64_bit else 20
-    
-    int_endian = '>i' if is_big_endian else '<i'
     int_endian_pair = '>ii' if is_big_endian else '<ii'
-    
+
     while True:
-        try:
-            code, length = struct.unpack(int_endian_pair, blendfile.read(8)) # 8 == sizeof(int) * 2
-        except IOError:
+        bhead = blendfile.read(sizeof_bhead)
+
+        if len(bhead) < sizeof_bhead:
             return None, 0, 0
-        
-        # finally read the rest of the bhead struct, pointer and 2 ints
-        blendfile.seek(sizeof_bhead - 8, os.SEEK_CUR)
+
+        code, length = struct.unpack(int_endian_pair, bhead[0:8]) # 8 == sizeof(int) * 2
 
         if code == REND:
             blendfile.seek(length, os.SEEK_CUR)
         else:
             break
+            
     
     if code != TEST:
         return None, 0, 0
@@ -86,12 +83,12 @@ def blend_extract_thumb(path):
         return None, 0, 0
 
     length -= 8 # sizeof(int) * 2
-    
+
     if length != x * y * 4:
         return None, 0, 0
-    
+
     image_buffer = blendfile.read(length)
-    
+
     if len(image_buffer) != length:
         return None, 0, 0
 
@@ -104,7 +101,7 @@ def write_png(buf, width, height):
     # reverse the vertical line order and add null bytes at the start
     width_byte_4 = width * 4
     raw_data = b"".join([b'\x00' + buf[span:span + width_byte_4] for span in range((height - 1) * width * 4, -1, - width_byte_4)])
-    
+
     def png_pack(png_tag, data):
         chunk_head = png_tag + data
         return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
@@ -117,6 +114,8 @@ def write_png(buf, width, height):
 
 
 if __name__ == '__main__':
+    import sys
+
     if len(sys.argv) < 2:
         print("Expected 2 arguments <input.blend> <output.png>")
     else: