or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

deep-zoom.mdindex.mdlow-level-api.mdslide-operations.md

deep-zoom.mddocs/

0

# Deep Zoom

1

2

Generate Deep Zoom tiles and metadata from OpenSlide objects for web-based slide viewing. Deep Zoom provides smooth zooming and panning by creating a pyramid of pre-rendered tiles at multiple resolution levels, enabling efficient web-based visualization of large whole-slide images.

3

4

```python

5

import openslide

6

from openslide.deepzoom import DeepZoomGenerator

7

from openslide import AbstractSlide

8

from PIL import Image

9

```

10

11

## Capabilities

12

13

### Deep Zoom Generator

14

15

Create Deep Zoom tile generators that convert whole-slide images into web-compatible tile pyramids.

16

17

```python { .api }

18

from openslide.deepzoom import DeepZoomGenerator

19

import openslide

20

21

class DeepZoomGenerator:

22

"""

23

Generates Deep Zoom tiles and metadata from slide objects.

24

25

Creates a pyramid of tiles at multiple resolution levels for efficient

26

web-based viewing with smooth zooming and panning.

27

"""

28

29

def __init__(self,

30

osr: openslide.AbstractSlide,

31

tile_size: int = 254,

32

overlap: int = 1,

33

limit_bounds: bool = False):

34

"""

35

Create a DeepZoomGenerator for a slide.

36

37

Args:

38

osr: Slide object (OpenSlide, ImageSlide, or AbstractSlide)

39

tile_size: Width and height of individual tiles. For best performance,

40

tile_size + 2 * overlap should be a power of two (default: 254)

41

overlap: Number of extra pixels to add to each interior edge of tiles

42

for seamless viewing (default: 1)

43

limit_bounds: If True, only render the non-empty slide region based

44

on bounds properties (default: False)

45

"""

46

47

BOUNDS_OFFSET_PROPS = (

48

openslide.PROPERTY_NAME_BOUNDS_X,

49

openslide.PROPERTY_NAME_BOUNDS_Y,

50

)

51

BOUNDS_SIZE_PROPS = (

52

openslide.PROPERTY_NAME_BOUNDS_WIDTH,

53

openslide.PROPERTY_NAME_BOUNDS_HEIGHT,

54

)

55

```

56

57

### Deep Zoom Properties

58

59

Access information about the Deep Zoom pyramid structure and tile organization.

60

61

```python { .api }

62

class DeepZoomGenerator:

63

@property

64

def level_count(self) -> int:

65

"""

66

Number of Deep Zoom levels in the image.

67

68

Level 0 is the smallest (most zoomed out), highest level is largest.

69

"""

70

71

@property

72

def level_tiles(self) -> tuple[tuple[int, int], ...]:

73

"""

74

Number of tiles in each Deep Zoom level.

75

76

Returns tuple of (tiles_x, tiles_y) for each level.

77

level_tiles[n] contains tile counts for level n.

78

"""

79

80

@property

81

def level_dimensions(self) -> tuple[tuple[int, int], ...]:

82

"""

83

Pixel dimensions of each Deep Zoom level.

84

85

Returns tuple of (pixels_x, pixels_y) for each level.

86

level_dimensions[n] contains pixel dimensions for level n.

87

"""

88

89

@property

90

def tile_count(self) -> int:

91

"""

92

Total number of tiles across all Deep Zoom levels.

93

"""

94

```

95

96

### Tile Generation

97

98

Generate individual tiles and tile coordinates for Deep Zoom viewing.

99

100

```python { .api }

101

class DeepZoomGenerator:

102

def get_tile(self, level: int, address: tuple[int, int]) -> Image.Image:

103

"""

104

Generate a tile image for the specified level and address.

105

106

Args:

107

level: Deep Zoom level number (0 = most zoomed out)

108

address: Tile address as (col, row) tuple within the level

109

110

Returns:

111

PIL.Image in RGB format containing the tile

112

113

Raises:

114

ValueError: If level or address is invalid

115

"""

116

117

def get_tile_coordinates(self, level: int, address: tuple[int, int]) -> tuple[tuple[int, int], int, tuple[int, int]]:

118

"""

119

Get OpenSlide read_region() arguments for a tile.

120

121

Most users should use get_tile() instead of calling read_region() directly.

122

123

Args:

124

level: Deep Zoom level number

125

address: Tile address as (col, row) tuple

126

127

Returns:

128

Tuple of (location, slide_level, size) for OpenSlide.read_region()

129

"""

130

131

def get_tile_dimensions(self, level: int, address: tuple[int, int]) -> tuple[int, int]:

132

"""

133

Get pixel dimensions of a specific tile.

134

135

Args:

136

level: Deep Zoom level number

137

address: Tile address as (col, row) tuple

138

139

Returns:

140

(pixels_x, pixels_y) tuple for the tile

141

"""

142

```

143

144

### DZI Metadata Generation

145

146

Generate Deep Zoom Image (DZI) XML metadata files for web viewers.

147

148

```python { .api }

149

class DeepZoomGenerator:

150

def get_dzi(self, format: str) -> str:

151

"""

152

Generate XML metadata for the Deep Zoom Image (.dzi) file.

153

154

Args:

155

format: Image format for tiles ('png' or 'jpeg')

156

157

Returns:

158

XML string containing DZI metadata

159

"""

160

```

161

162

## Usage Examples

163

164

### Basic Deep Zoom Generation

165

166

```python

167

import openslide

168

from openslide.deepzoom import DeepZoomGenerator

169

170

# Open a slide

171

with openslide.open_slide("slide.svs") as slide:

172

# Create Deep Zoom generator

173

dz = DeepZoomGenerator(slide, tile_size=254, overlap=1)

174

175

print(f"Deep Zoom levels: {dz.level_count}")

176

print(f"Total tiles: {dz.tile_count}")

177

178

# Generate DZI metadata

179

dzi_xml = dz.get_dzi('jpeg')

180

with open('slide.dzi', 'w') as f:

181

f.write(dzi_xml)

182

183

# Generate some tiles

184

for level in range(dz.level_count):

185

tiles_x, tiles_y = dz.level_tiles[level]

186

print(f"Level {level}: {tiles_x}x{tiles_y} tiles")

187

188

# Generate first tile of each level

189

if tiles_x > 0 and tiles_y > 0:

190

tile = dz.get_tile(level, (0, 0))

191

tile.save(f'tile_{level}_0_0.jpg')

192

```

193

194

### Complete Tile Pyramid Generation

195

196

```python

197

import os

198

import openslide

199

from openslide.deepzoom import DeepZoomGenerator

200

201

def generate_tiles(slide_path, output_dir, tile_format='jpeg'):

202

"""Generate complete Deep Zoom tile pyramid for a slide."""

203

204

with openslide.open_slide(slide_path) as slide:

205

# Create Deep Zoom generator

206

dz = DeepZoomGenerator(slide, tile_size=254, overlap=1)

207

208

# Create output directory

209

os.makedirs(output_dir, exist_ok=True)

210

211

# Save DZI metadata

212

dzi_path = os.path.join(output_dir, 'slide.dzi')

213

with open(dzi_path, 'w') as f:

214

f.write(dz.get_dzi(tile_format))

215

216

# Create tiles directory

217

tiles_dir = os.path.join(output_dir, 'slide_files')

218

os.makedirs(tiles_dir, exist_ok=True)

219

220

# Generate all tiles

221

for level in range(dz.level_count):

222

level_dir = os.path.join(tiles_dir, str(level))

223

os.makedirs(level_dir, exist_ok=True)

224

225

tiles_x, tiles_y = dz.level_tiles[level]

226

print(f"Generating level {level}: {tiles_x}x{tiles_y} tiles")

227

228

for col in range(tiles_x):

229

for row in range(tiles_y):

230

tile = dz.get_tile(level, (col, row))

231

tile_path = os.path.join(level_dir, f'{col}_{row}.{tile_format}')

232

233

if tile_format == 'jpeg':

234

tile.save(tile_path, 'JPEG', quality=90)

235

else:

236

tile.save(tile_path, 'PNG')

237

238

# Usage

239

generate_tiles('slide.svs', 'output_tiles', 'jpeg')

240

```

241

242

### Bounds-Limited Deep Zoom

243

244

```python

245

import openslide

246

from openslide.deepzoom import DeepZoomGenerator

247

248

# Open a slide

249

with openslide.open_slide("slide.svs") as slide:

250

# Check if slide has bounds information

251

bounds_props = [

252

openslide.PROPERTY_NAME_BOUNDS_X,

253

openslide.PROPERTY_NAME_BOUNDS_Y,

254

openslide.PROPERTY_NAME_BOUNDS_WIDTH,

255

openslide.PROPERTY_NAME_BOUNDS_HEIGHT

256

]

257

258

has_bounds = all(prop in slide.properties for prop in bounds_props)

259

260

if has_bounds:

261

print("Slide has bounds information - using limited bounds")

262

# Create generator with bounds limiting

263

dz = DeepZoomGenerator(slide, limit_bounds=True)

264

265

# Show bounds information

266

bounds_x = int(slide.properties[openslide.PROPERTY_NAME_BOUNDS_X])

267

bounds_y = int(slide.properties[openslide.PROPERTY_NAME_BOUNDS_Y])

268

bounds_w = int(slide.properties[openslide.PROPERTY_NAME_BOUNDS_WIDTH])

269

bounds_h = int(slide.properties[openslide.PROPERTY_NAME_BOUNDS_HEIGHT])

270

271

print(f"Bounds: ({bounds_x}, {bounds_y}) {bounds_w}x{bounds_h}")

272

print(f"Original dimensions: {slide.dimensions}")

273

print(f"Deep Zoom dimensions: {dz.level_dimensions[-1]}")

274

else:

275

print("No bounds information - using full slide")

276

dz = DeepZoomGenerator(slide, limit_bounds=False)

277

278

# Generate some tiles

279

highest_level = dz.level_count - 1

280

tile = dz.get_tile(highest_level, (0, 0))

281

tile.save('bounds_tile.jpg')

282

```

283

284

### Custom Tile Sizes and Overlap

285

286

```python

287

import openslide

288

from openslide.deepzoom import DeepZoomGenerator

289

290

with openslide.open_slide("slide.svs") as slide:

291

# Different configurations for different use cases

292

293

# High quality with larger tiles (good for detailed viewing)

294

dz_hq = DeepZoomGenerator(slide, tile_size=510, overlap=2)

295

296

# Fast loading with smaller tiles (good for overview)

297

dz_fast = DeepZoomGenerator(slide, tile_size=126, overlap=1)

298

299

# Standard configuration (tile_size + 2*overlap = 256, power of 2)

300

dz_standard = DeepZoomGenerator(slide, tile_size=254, overlap=1)

301

302

print("Configuration comparison:")

303

print(f"High quality: {dz_hq.tile_count} tiles")

304

print(f"Fast loading: {dz_fast.tile_count} tiles")

305

print(f"Standard: {dz_standard.tile_count} tiles")

306

307

# Generate sample tiles with different configurations

308

for name, dz in [('hq', dz_hq), ('fast', dz_fast), ('standard', dz_standard)]:

309

if dz.level_count > 0:

310

mid_level = dz.level_count // 2

311

tiles_x, tiles_y = dz.level_tiles[mid_level]

312

if tiles_x > 0 and tiles_y > 0:

313

tile = dz.get_tile(mid_level, (0, 0))

314

tile.save(f'sample_{name}.jpg')

315

```

316

317

### Web Viewer Integration

318

319

```python

320

import json

321

import openslide

322

from openslide.deepzoom import DeepZoomGenerator

323

324

def create_viewer_config(slide_path, output_path):

325

"""Create configuration for OpenSeadragon web viewer."""

326

327

with openslide.open_slide(slide_path) as slide:

328

dz = DeepZoomGenerator(slide, tile_size=254, overlap=1)

329

330

# Extract slide information

331

config = {

332

'slide_info': {

333

'dimensions': slide.dimensions,

334

'level_count': slide.level_count,

335

'level_dimensions': slide.level_dimensions,

336

'properties': dict(slide.properties),

337

'associated_images': list(slide.associated_images.keys())

338

},

339

'deepzoom_info': {

340

'level_count': dz.level_count,

341

'level_dimensions': dz.level_dimensions,

342

'level_tiles': dz.level_tiles,

343

'tile_count': dz.tile_count,

344

'tile_size': 254,

345

'overlap': 1

346

},

347

'viewer_config': {

348

'tileSources': 'slide.dzi',

349

'prefixUrl': 'openseadragon/images/',

350

'showNavigator': True,

351

'showRotationControl': True,

352

'showHomeControl': True,

353

'showZoomControl': True,

354

'showFullPageControl': True

355

}

356

}

357

358

# Save configuration

359

with open(output_path, 'w') as f:

360

json.dump(config, f, indent=2)

361

362

return config

363

364

# Create viewer configuration

365

config = create_viewer_config('slide.svs', 'viewer_config.json')

366

print(f"Created viewer config for {config['slide_info']['dimensions']} slide")

367

```