@@ -46,7 +46,13 @@ class DeepZoomGenerator:
4646 openslide .PROPERTY_NAME_BOUNDS_HEIGHT ,
4747 )
4848
49- def __init__ (self , osr , tile_size = 254 , overlap = 1 , limit_bounds = False ):
49+ def __init__ (
50+ self ,
51+ osr : openslide .AbstractSlide ,
52+ tile_size : int = 254 ,
53+ overlap : int = 1 ,
54+ limit_bounds : bool = False ,
55+ ):
5056 """Create a DeepZoomGenerator wrapping an OpenSlide object.
5157
5258 osr: a slide object.
@@ -101,7 +107,7 @@ def __init__(self, osr, tile_size=254, overlap=1, limit_bounds=False):
101107 self ._z_dimensions = tuple (reversed (z_dimensions ))
102108
103109 # Tile
104- def tiles (z_lim ) :
110+ def tiles (z_lim : int ) -> int :
105111 return int (math .ceil (z_lim / self ._z_t_downsample ))
106112
107113 self ._t_dimensions = tuple (
@@ -112,7 +118,8 @@ def tiles(z_lim):
112118 self ._dz_levels = len (self ._z_dimensions )
113119
114120 # Total downsamples for each Deep Zoom level
115- l0_z_downsamples = tuple (
121+ # mypy infers this as a tuple[Any, ...] due to the ** operator
122+ l0_z_downsamples : tuple [int , ...] = tuple (
116123 2 ** (self ._dz_levels - dz_level - 1 ) for dz_level in range (self ._dz_levels )
117124 )
118125
@@ -134,7 +141,7 @@ def tiles(z_lim):
134141 openslide .PROPERTY_NAME_BACKGROUND_COLOR , 'ffffff'
135142 )
136143
137- def __repr__ (self ):
144+ def __repr__ (self ) -> str :
138145 return '{}({!r}, tile_size={!r}, overlap={!r}, limit_bounds={!r})' .format (
139146 self .__class__ .__name__ ,
140147 self ._osr ,
@@ -144,26 +151,26 @@ def __repr__(self):
144151 )
145152
146153 @property
147- def level_count (self ):
154+ def level_count (self ) -> int :
148155 """The number of Deep Zoom levels in the image."""
149156 return self ._dz_levels
150157
151158 @property
152- def level_tiles (self ):
159+ def level_tiles (self ) -> tuple [ tuple [ int , int ], ...] :
153160 """A list of (tiles_x, tiles_y) tuples for each Deep Zoom level."""
154161 return self ._t_dimensions
155162
156163 @property
157- def level_dimensions (self ):
164+ def level_dimensions (self ) -> tuple [ tuple [ int , ...], ...] :
158165 """A list of (pixels_x, pixels_y) tuples for each Deep Zoom level."""
159166 return self ._z_dimensions
160167
161168 @property
162- def tile_count (self ):
169+ def tile_count (self ) -> int :
163170 """The total number of Deep Zoom tiles in the image."""
164171 return sum (t_cols * t_rows for t_cols , t_rows in self ._t_dimensions )
165172
166- def get_tile (self , level , address ) :
173+ def get_tile (self , level : int , address : tuple [ int , int ]) -> Image . Image :
167174 """Return an RGB PIL.Image for a tile.
168175
169176 level: the Deep Zoom level.
@@ -191,7 +198,9 @@ def get_tile(self, level, address):
191198
192199 return tile
193200
194- def _get_tile_info (self , dz_level , t_location ):
201+ def _get_tile_info (
202+ self , dz_level : int , t_location : tuple [int , int ]
203+ ) -> tuple [tuple [tuple [int , int ], int , tuple [int , int ]], tuple [int , int ]]:
195204 # Check parameters
196205 if dz_level < 0 or dz_level >= self ._dz_levels :
197206 raise ValueError ("Invalid level" )
@@ -210,42 +219,62 @@ def _get_tile_info(self, dz_level, t_location):
210219 )
211220
212221 # Get final size of the tile
213- z_size = tuple (
214- min (self . _z_t_downsample , z_lim - self . _z_t_downsample * t ) + z_tl + z_br
215- for t , z_lim , z_tl , z_br in zip (
216- t_location , self ._z_dimensions [dz_level ], z_overlap_tl , z_overlap_br
222+ z_size = (
223+ min (
224+ self . _z_t_downsample ,
225+ self ._z_dimensions [dz_level ][ 0 ] - self . _z_t_downsample * t_location [ 0 ],
217226 )
227+ + z_overlap_tl [0 ]
228+ + z_overlap_br [0 ],
229+ min (
230+ self ._z_t_downsample ,
231+ self ._z_dimensions [dz_level ][1 ] - self ._z_t_downsample * t_location [1 ],
232+ )
233+ + z_overlap_tl [1 ]
234+ + z_overlap_br [1 ],
218235 )
219236
220237 # Obtain the region coordinates
221- z_location = [ self ._z_from_t (t ) for t in t_location ]
222- l_location = [
223- self ._l_from_z (dz_level , z - z_tl )
224- for z , z_tl in zip ( z_location , z_overlap_tl )
225- ]
238+ z_location = ( self ._z_from_t (t_location [ 0 ]), self . _z_from_t ( t_location [ 1 ]))
239+ l_location = (
240+ self ._l_from_z (dz_level , z_location [ 0 ] - z_overlap_tl [ 0 ]),
241+ self . _l_from_z ( dz_level , z_location [ 1 ] - z_overlap_tl [ 1 ]),
242+ )
226243 # Round location down and size up, and add offset of active area
227- l0_location = tuple (
228- int (self ._l0_from_l (slide_level , l ) + l0_off )
229- for l , l0_off in zip ( l_location , self ._l0_offset )
244+ l0_location = (
245+ int (self ._l0_from_l (slide_level , l_location [ 0 ] ) + self . _l0_offset [ 0 ]),
246+ int ( self . _l0_from_l ( slide_level , l_location [ 1 ]) + self ._l0_offset [ 1 ]),
230247 )
231- l_size = tuple (
232- int (min (math .ceil (self ._l_from_z (dz_level , dz )), l_lim - math .ceil (l )))
233- for l , dz , l_lim in zip (l_location , z_size , self ._l_dimensions [slide_level ])
248+ l_size = (
249+ int (
250+ min (
251+ math .ceil (self ._l_from_z (dz_level , z_size [0 ])),
252+ self ._l_dimensions [slide_level ][0 ] - math .ceil (l_location [0 ]),
253+ )
254+ ),
255+ int (
256+ min (
257+ math .ceil (self ._l_from_z (dz_level , z_size [1 ])),
258+ self ._l_dimensions [slide_level ][1 ] - math .ceil (l_location [1 ]),
259+ )
260+ ),
234261 )
235262
236263 # Return read_region() parameters plus tile size for final scaling
237264 return ((l0_location , slide_level , l_size ), z_size )
238265
239- def _l0_from_l (self , slide_level , l ) :
266+ def _l0_from_l (self , slide_level : int , l : float ) -> float :
240267 return self ._l0_l_downsamples [slide_level ] * l
241268
242- def _l_from_z (self , dz_level , z ) :
269+ def _l_from_z (self , dz_level : int , z : int ) -> float :
243270 return self ._l_z_downsamples [dz_level ] * z
244271
245- def _z_from_t (self , t ) :
272+ def _z_from_t (self , t : int ) -> int :
246273 return self ._z_t_downsample * t
247274
248- def get_tile_coordinates (self , level , address ):
275+ def get_tile_coordinates (
276+ self , level : int , address : tuple [int , int ]
277+ ) -> tuple [tuple [int , int ], int , tuple [int , int ]]:
249278 """Return the OpenSlide.read_region() arguments for the specified tile.
250279
251280 Most users should call get_tile() rather than calling
@@ -256,15 +285,17 @@ def get_tile_coordinates(self, level, address):
256285 tuple."""
257286 return self ._get_tile_info (level , address )[0 ]
258287
259- def get_tile_dimensions (self , level , address ):
288+ def get_tile_dimensions (
289+ self , level : int , address : tuple [int , int ]
290+ ) -> tuple [int , int ]:
260291 """Return a (pixels_x, pixels_y) tuple for the specified tile.
261292
262293 level: the Deep Zoom level.
263294 address: the address of the tile within the level as a (col, row)
264295 tuple."""
265296 return self ._get_tile_info (level , address )[1 ]
266297
267- def get_dzi (self , format ) :
298+ def get_dzi (self , format : str ) -> str :
268299 """Return a string containing the XML metadata for the .dzi file.
269300
270301 format: the format of the individual tiles ('png' or 'jpeg')"""
0 commit comments