1
1
#
2
2
# openslide-python - Python bindings for the OpenSlide library
3
3
#
4
- # Copyright (c) 2010-2011 Carnegie Mellon University
4
+ # Copyright (c) 2010-2013 Carnegie Mellon University
5
5
#
6
6
# This library is free software; you can redistribute it and/or modify it
7
7
# under the terms of version 2.1 of the GNU Lesser General Public License
@@ -91,6 +91,25 @@ def from_param(cls, obj):
91
91
raise ValueError ("Passing closed slide object" )
92
92
return obj
93
93
94
+ class _utf8_p (object ):
95
+ """Wrapper class to convert string arguments to bytes."""
96
+
97
+ if sys .version [0 ] == '2' :
98
+ _bytes_type = str
99
+ _str_type = unicode
100
+ else :
101
+ _bytes_type = bytes
102
+ _str_type = str
103
+
104
+ @classmethod
105
+ def from_param (cls , obj ):
106
+ if isinstance (obj , cls ._bytes_type ):
107
+ return obj
108
+ elif isinstance (obj , cls ._str_type ):
109
+ return obj .encode ()
110
+ else :
111
+ raise TypeError ('Incorrect type' )
112
+
94
113
# check for errors opening an image file and wrap the resulting handle
95
114
def _check_open (result , _func , _args ):
96
115
if result is None :
@@ -106,22 +125,29 @@ def _check_open(result, _func, _args):
106
125
def _check_close (_result , _func , args ):
107
126
args [0 ].invalidate ()
108
127
128
+ # Convert returned byte array, if present, into a string
129
+ def _check_string (result , func , _args ):
130
+ if func .restype is c_char_p and result is not None :
131
+ return result .decode (errors = 'replace' )
132
+ else :
133
+ return result
134
+
109
135
# check if the library got into an error state after each library call
110
- def _check_error (result , _func , args ):
136
+ def _check_error (result , func , args ):
111
137
err = get_error (args [0 ])
112
138
if err is not None :
113
139
raise OpenSlideError (err )
114
- return result
140
+ return _check_string ( result , func , args )
115
141
116
- # Convert returned NULL-terminated string array into a list
142
+ # Convert returned NULL-terminated char** into a list of strings
117
143
def _check_name_list (result , func , args ):
118
144
_check_error (result , func , args )
119
145
names = []
120
146
for i in count ():
121
147
name = result [i ]
122
148
if not name :
123
149
break
124
- names .append (name )
150
+ names .append (name . decode ( errors = 'replace' ) )
125
151
return names
126
152
127
153
# resolve and return an OpenSlide function with the specified properties
@@ -145,13 +171,13 @@ def _load_image(buf, size):
145
171
return PIL .Image .frombuffer ('RGBA' , size , buf , 'raw' , 'RGBa' , 0 , 1 )
146
172
147
173
try :
148
- get_version = _func ('openslide_get_version' , c_char_p , [], None )
174
+ get_version = _func ('openslide_get_version' , c_char_p , [], _check_string )
149
175
except AttributeError :
150
176
raise OpenSlideError ('OpenSlide >= 3.3.0 required' )
151
177
152
- can_open = _func ('openslide_can_open' , c_bool , [c_char_p ], None )
178
+ can_open = _func ('openslide_can_open' , c_bool , [_utf8_p ], None )
153
179
154
- open = _func ('openslide_open' , c_void_p , [c_char_p ], _check_open )
180
+ open = _func ('openslide_open' , c_void_p , [_utf8_p ], _check_open )
155
181
156
182
close = _func ('openslide_close' , None , [_OpenSlide ], _check_close )
157
183
@@ -188,27 +214,27 @@ def read_region(slide, x, y, level, w, h):
188
214
_read_region (slide , buf , x , y , level , w , h )
189
215
return _load_image (buf , (w , h ))
190
216
191
- get_error = _func ('openslide_get_error' , c_char_p , [_OpenSlide ], None )
217
+ get_error = _func ('openslide_get_error' , c_char_p , [_OpenSlide ], _check_string )
192
218
193
219
get_property_names = _func ('openslide_get_property_names' , POINTER (c_char_p ),
194
220
[_OpenSlide ], _check_name_list )
195
221
196
222
get_property_value = _func ('openslide_get_property_value' , c_char_p ,
197
- [_OpenSlide , c_char_p ])
223
+ [_OpenSlide , _utf8_p ])
198
224
199
225
get_associated_image_names = _func ('openslide_get_associated_image_names' ,
200
226
POINTER (c_char_p ), [_OpenSlide ], _check_name_list )
201
227
202
228
_get_associated_image_dimensions = \
203
229
_func ('openslide_get_associated_image_dimensions' , None ,
204
- [_OpenSlide , c_char_p , POINTER (c_int64 ), POINTER (c_int64 )])
230
+ [_OpenSlide , _utf8_p , POINTER (c_int64 ), POINTER (c_int64 )])
205
231
def get_associated_image_dimensions (slide , name ):
206
232
w , h = c_int64 (), c_int64 ()
207
233
_get_associated_image_dimensions (slide , name , byref (w ), byref (h ))
208
234
return w .value , h .value
209
235
210
236
_read_associated_image = _func ('openslide_read_associated_image' , None ,
211
- [_OpenSlide , c_char_p , POINTER (c_uint32 )])
237
+ [_OpenSlide , _utf8_p , POINTER (c_uint32 )])
212
238
def read_associated_image (slide , name ):
213
239
w , h = get_associated_image_dimensions (slide , name )
214
240
buf = (w * h * c_uint32 )()
0 commit comments