Skip to content

Commit fcba2f9

Browse files
committed
RF: Decode B64* data to bytearrays for writable numpy arrays
1 parent 5edbbe6 commit fcba2f9

File tree

1 file changed

+23
-25
lines changed

1 file changed

+23
-25
lines changed

nibabel/gifti/parse_gifti_fast.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,43 +33,41 @@ class GiftiParseError(ExpatError):
3333

3434
def read_data_block(encoding, endian, ordering, datatype, shape, data):
3535
""" Tries to unzip, decode, parse the funny string data """
36-
ord = array_index_order_codes.npcode[ordering]
3736
enclabel = gifti_encoding_codes.label[encoding]
37+
dtype = data_type_codes.type[datatype]
3838
if enclabel == 'ASCII':
3939
# GIFTI_ENCODING_ASCII
4040
c = StringIO(data)
41-
da = np.loadtxt(c)
42-
da = da.astype(data_type_codes.type[datatype])
41+
da = np.loadtxt(c, dtype=dtype)
4342
return da # independent of the endianness
4443

45-
elif enclabel == 'B64BIN':
46-
# GIFTI_ENCODING_B64BIN
47-
dec = base64.b64decode(data.encode('ascii'))
48-
dt = data_type_codes.type[datatype]
49-
sh = tuple(shape)
50-
newarr = np.frombuffer(dec, dtype=dt)
51-
if len(newarr.shape) != len(sh):
52-
newarr = newarr.reshape(sh, order=ord)
53-
54-
elif enclabel == 'B64GZ':
55-
# GIFTI_ENCODING_B64GZ
56-
# convert to bytes array for python 3.2
57-
# http://www.diveintopython3.net/strings.html#byte-arrays
58-
dec = base64.b64decode(data.encode('ascii'))
59-
zdec = zlib.decompress(dec)
60-
dt = data_type_codes.type[datatype]
61-
sh = tuple(shape)
62-
newarr = np.frombuffer(zdec, dtype=dt)
63-
if len(newarr.shape) != len(sh):
64-
newarr = newarr.reshape(sh, order=ord)
65-
6644
elif enclabel == 'External':
6745
# GIFTI_ENCODING_EXTBIN
6846
raise NotImplementedError("In what format are the external files?")
6947

70-
else:
48+
elif enclabel not in ('B64BIN', 'B64GZ'):
7149
return 0
7250

51+
# Numpy arrays created from bytes objects are read-only.
52+
# Neither b64decode nor decompress will return bytearrays, and there
53+
# are not equivalents to fobj.readinto to allow us to pass them, so
54+
# there is not a simple way to avoid making copies.
55+
# If this becomes a problem, we should write a decoding interface with
56+
# a tunable chunk size.
57+
dec = base64.b64decode(data.encode('ascii'))
58+
if enclabel == 'B64BIN':
59+
# GIFTI_ENCODING_B64BIN
60+
buff = bytearray(dec)
61+
else:
62+
# GIFTI_ENCODING_B64GZ
63+
buff = bytearray(zlib.decompress(dec))
64+
del dec
65+
66+
sh = tuple(shape)
67+
newarr = np.frombuffer(buff, dtype=dtype)
68+
if len(newarr.shape) != len(sh):
69+
newarr = newarr.reshape(sh, order=array_index_order_codes.npcode[ordering])
70+
7371
# check if we need to byteswap
7472
required_byteorder = gifti_endian_codes.byteorder[endian]
7573
if (required_byteorder in ('big', 'little') and

0 commit comments

Comments
 (0)