0

I'm trying to write my "personal"(without using any modules or functions : struct,float....,int....,...) python version of STL binary file reader, according to WIKIPEDIA : A binary STL file contains :

  • a 80-character (byte) headern which is generally ignored.

  • a 4-byte unsigned integer indicating the number of triangular facets in the file.

  • Each triangle is described by twelve 32-bit floating-point numbers: three for the normal and then three for the X/Y/Z coordinate of each vertex – just as with the ASCII version of STL. After these follows a 2-byte ("short") unsigned integer that is the "attribute byte count" – in the standard format, this should be zero because most software does not understand anything else. (((3+3+3)+3)*4+2=50 bytes for each point)

--Floating-point numbers are represented as IEEE floating-point numbers and are assumed to be little-endian--

With the help of two saviors I discovered how unsigned integers are stored, I can figure out the number of triangular facets in the file with 3 methods (computed by hand ) :

def int_from_bytes(inbytes): # ShadowRanger's
     res = 0
     for i, b in enumerate(inbytes):
         res |= b << (i * 8)  
     return res

or

def int_from_bytes(inbytes): # ShadowRanger's
    res = 0
    for b in inbytes:
        res <<= 8  # Adjust bytes seen so far to make room for new byte
        res |= b   # Mask in new byte
    return res

or

def unsigned_int(s): # Robᵩ's
    result = 0
    for ch in s[::-1]:
        result *= 256
        result += ch
    return result

Now I have to convert the rest of the file (3rd item in the list):Floating-point numbers

for the first point the 50-bytes are :

b'\x9a'b'\xa3' b'\x14' b'\xbe' b'\x05' b'$' b'\x85' b'\xbe' b'N' b'b'  
b't' b'?' b'\xcd' b'\xa6' b'\x04' b'\xc4' b'\xfb' b';' b'\xd4' b'\xc1' 
b'\x84' b'w' b'\x81' b'A' b'\xcd' b'\xa6' b'\x04' b'\xc4' b'\xa5' b'\x15' 
b'\xd3' b'\xc1' b'\xb2' b'\xc7' b'\x81' b'A' b'\xef' b'\xa6' b'\x04' 
b'\xc4' b'\x81' b'\x14' b'\xd3' b'\xc1' b'Y' b'\xc7' b'\x81' b'A' b'\x00' 
b'\x00' 

How can I convert this by hand, What is the principle of the representation, what rules should I know to do the conversion by hand (some bytes don't start with \x ). ?

Thank you for your time.

7
  • What version of Python are you using? Commented Dec 9, 2016 at 18:40
  • Is there an actual purpose to this or are you just trying to see how far you can get? Commented Dec 9, 2016 at 18:45
  • Also why are you trying to avoid using the struct module? Commented Dec 9, 2016 at 18:45
  • 1
    Some of the bytes don't start with \x because their value happens to be the character code of an ascii character, so they're simply displayed as a (b-prefixed) quoted version character itself. Commented Dec 9, 2016 at 18:55
  • 1
    struct is part of the set of modules that comes with Python so avoiding it is silly. Commented Dec 9, 2016 at 19:07

1 Answer 1

2

Like this:

def int_from_bytes(inbytes):
    res = 0
    shft = 0
    for b in inbytes:
        res |= ord(b) << shft
        shft += 8
    return res

def float_from_bytes(inbytes):
    bits = int_from_bytes(inbytes)
    mantissa = ((bits&8388607)/8388608.0)
    exponent = (bits>>23)&255
    sign = 1.0 if bits>>31 ==0 else -1.0
    if exponent != 0:
        mantissa+=1.0
    elif mantissa==0.0:
        return sign*0.0
    return sign*pow(2.0,exponent-127)*mantissa


print float_from_bytes('\x9a\xa3\x14\xbe')
print float_from_bytes('\x00\x00\x00\x40')
print float_from_bytes('\x00\x00\xC0\xbf')

output:

-0.145155340433
2.0
-1.5

The format is IEEE-754 floating point. Try this out to see what each bit means: https://www.h-schmidt.net/FloatConverter/IEEE754.html

Sign up to request clarification or add additional context in comments.

3 Comments

One should note that this doesn't handle denormals or non-finite numbers, but these are all somewhat unusual cases so you might be fine without such support.
@DietrichEpp oh yeah -- fixed to handle denormals.
I would use hex for the magic constants instead of decimal. But congratulations for giving a good answer to a bad question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.