Tiling System¶
This document provides a comprehensive overview of the tiling system architecture, explaining how large images are converted into pyramidal tile structures and how such tiles are stored to be then retrieved and rendered on the interface.
Overview¶
The tiling system is responsible for:
Converting large images into pyramidal tile structures
Storing tiles on disk for persistence
Caching tiles in memory for fast access
Providing tiles on demand for display
Pausing and resuming tile providers during process-based conversion
Cleaning up stale tile data automatically
The system uses a tile pyramid structure where each level represents the image at a different zoom level. Level 0 contains a single overview tile, and higher levels contain progressively more tiles at higher resolutions.
Architecture¶
The tiling system consists of the following components:
┌─────────────────────────────────────────────────────────────────┐
│ TileManager │
│ (Coordinates tile requests, caching, and provider routing) │
│ • init() / shutdown() — lifecycle management │
│ • pause() / resume() — provider control │
└─────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ TileCache │ │ TileProviders │
│ (Memory caching) │ │ (Tile loading/gen) │
│ 2-tier: perm/temp │ └─────────────────────┘
└─────────────────────┘ │
┌─────────┼──────────────┐
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│StaticTileProvider │ │DynamicTileProvider│
│ (tiled images) │ │(Procedural gen) │
│ • FernTileProvider│ │ │
└───────────────────┘ └───────────────────┘
│ │
│ ▼
│ ┌───────────────────┐
──────────🢒 │ TileStore │
│ (Disk storage) │
└───────────────────┘
│
▼
┌───────────────────┐
│ cleanuptilestore │
│ (CLI + auto) │
└───────────────────┘
**Tile request and loading flow**
┌─────────────────────────┐
│ MediaObject needs tile │
│ at specific zoom level │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ TileManager.get_tile() │
│ or get_tile_robust() │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ Check TileCache │
│ (in-memory LRU cache) │
└────────────┬────────────┘
│
┌────┴────┐
│ │
CACHE HIT CACHE MISS
│ │
▼ ▼
┌──────────┐ ┌────────────────────┐
│ Return │ │ load_tile() — │
│ cached │ │ Queue tile request │
│ tile │ │ to provider (LIFO) │
└──────────┘ └─────────┬──────────┘
│
▼
┌─────────────────────┐
│ TileProvider Thread │
│ processes request │
└─────────┬───────────┘
│
▼
┌────────────────────┐
│ Check TileStore │
│ (disk cache) │
└─────────┬──────────┘
│
┌────┴────┐
│ │
FOUND NOT FOUND
│ │
▼ ▼
┌─────────┐ ┌──────────┐
│ Load │ │ Generate │
│ from │ │ or load │
│ disk │ │ from src │
└────┬────┘ └─────┬────┘
└─────┬──────┘
▼
┌─────────────────────┐
│ Store in TileCache │
└─────────┬───────────┘
▼
┌─────────────────────┐
│ Save to TileStore │
│ (if static provider)│
└─────────┬───────────┘
▼
┌────────────────────┐
│ Return tile │
└────────────────────┘
Component Details¶
Tile¶
The Tile class is a wrapper around image data (QImage/PIL) providing operations
for manipulation and rendering.
Key Operations:
crop(bbox): Extract a rectangular region from the tileresize(width, height): Scale the tile to new dimensionssave(filename): Write the tile to diskdraw(painter, x, y): Render the tile using a QPainter
Factory Functions:
new(width, height): Create an empty tilefromstring(string, width, height): Create a tile from raw pixel datamerged(t1, t2, t3, t4): Combine four tiles into one (2×2 grid)
Tiler¶
The Tiler class converts source images into pyramidal tile structures. It is an
abstract base class that runs as a separate thread and uses an internal
ThreadPoolExecutor for parallel tile creation within each row.
Tile Pyramid Structure:
For an image with dimensions W × H and tile size T:
T (tile size): The width and height of each square tile in pixels (typically 256×256)
W: Image width in pixels
H: Image height in pixels
Maximum Tile Level Formula:
maxtilelevel = ceil(log2(max(W, H) / T))
This formula calculates how many pyramid levels are needed to represent the full-resolution image:
max(W, H) / T: How many tiles would fit along the longest dimension at full resolutionlog2(...): The logarithm base-2 tells us how many times we need to divide by 2 to get down to 1 tile. Since each pyramid level halves the resolution, this gives us the number of levels needed.ceil(...): The ceiling function rounds up to the nearest integer, ensuring we have enough levels even if the division isn’t exact (e.g.,ceil(2.3) = 3,ceil(4.0) = 4)
Tiles at Level L Formula:
ceil(W / (T × 2^(maxtilelevel - L))) × ceil(H / (T × 2^(maxtilelevel - L)))
This formula calculates how many tiles exist at a specific pyramid level:
2^(maxtilelevel - L): The scaling factor - how much smaller level L is compared to the maximum levelAt
L = maxtilelevel(full resolution):2^0 = 1(no scaling)At
L = maxtilelevel - 1:2^1 = 2(half resolution, 2× smaller)At
L = 0(overview):2^maxtilelevel(smallest, 2^maxtilelevel× smaller)
T × 2^(maxtilelevel - L): The effective size each tile covers at level LW / (T × 2^(...)): How many tiles fit horizontallyH / (T × 2^(...)): How many tiles fit verticallyceil(...): Round up to ensure partial tiles are counted
Example: A 1024×1024 image with 256×256 tiles:
Level 0: 1 tile (1×1) - Overview (each tile covers 1024×1024 pixels)
Level 1: 4 tiles (2×2) - Half resolution (each tile covers 512×512 pixels)
Level 2: 16 tiles (4×4) - Full resolution (each tile covers 256×256 pixels)
Total: 1 + 4 + 16 = 21 tiles
Tiling Process:
Calculate Dimensions: Determine the number of tiles and pyramid levels
Read Scanlines: Read the source image row by row using
_scanchunk()Create Base Tiles: Divide rows into tiles at the maximum level using a
ThreadPoolExecutorper row for parallel column processingMerge Upward: Combine 2×2 tile groups to create lower-level tiles
Save Tiles: Write each tile to disk via TileStore. Each tile save increments the progress counter:
progress = saved_count / numtilesWrite Metadata: Store image dimensions, tile size, and format
Concrete Subclasses:
PPMTiler: Reads PPM/PGM format images. Provides_scanchunk()as a callable attribute that readsbytes_per_pixel * widthbytes at a time. Includesread_ppm_header()(validates P6 format, maxval=255) and a__del__for output file cleanup.
Extension Points:
Subclasses must provide these instance attributes (declared but uninitialized in the base class):
_width: Image width in pixels_height: Image height in pixels_bytes_per_pixel: Number of color channels (1 for grayscale, 3 for RGB)_scanchunk: Callable that returns raw pixel data for the next row
Parallel Tile Processing:
Within each row, tiles are created in parallel using a ThreadPoolExecutor:
# In Tiler.__tiles(), for each row:
workers = min(numtiles_across, cpu_count())
with ThreadPoolExecutor(max_workers=workers) as executor:
args = [(self, row, col, tilelevel, ...) for col in range(numtiles_across)]
for tile_data in executor.map(_make_tile, args):
__savetile(tile_data, tilelevel, row, col)
The _make_tile() module-level function creates a Tile from raw pixel data
via Tile.fromstring() in a thread-safe manner (no Qt objects are constructed
on worker threads). The executor is shut down in a finally block to ensure
cleanup even on errors.
Progress Tracking:
The progress property returns a 0.0–1.0 float computed as
saved_tiles / total_tiles. Each successful __savetile() call increments
the counter, providing smooth progress indication during the tiling phase.
Process-Based Tiling (tilerrunner)¶
The tilerrunner module provides process-based tiling execution for parallel
image tiling, avoiding threading conflicts between pyvips, TileManager threads,
and Qt. This is the recommended approach for tiling — the thread-based
Tiler class is a legacy API for direct use only.
Architecture:
The tilerrunner module uses ProcessPoolExecutor with 'spawn' context
(default, for safety). The context can be overridden via the PYZUI_MP_CONTEXT
environment variable (see ../zooui/tilerrunner for details).
Key Functions:
from zooui.tilesystem.tiler import tilerrunner
# Initialize process pool (optional, auto-initialized on first use)
tilerrunner.init(max_workers=2)
# Submit tiling job
future = tilerrunner.submit_tiling(
infile='image.ppm',
media_id='my_image',
filext='jpg',
tilesize=256
)
# Create handle for tracking
handle = tilerrunner.TilingHandle(future, 'image.ppm', 'my_image')
# Check progress
if handle.progress == 1.0:
if handle.error:
print(f"Tiling failed: {handle.error}")
else:
print("Tiling complete!")
# Shutdown pool when done
tilerrunner.shutdown()
TilingHandle Class:
The TilingHandle wraps a Future and provides a compatible interface
with the thread-based Tiler class:
progress: Returns 0.0 while running and 1.0 when doneerror: Error message if tiling failed, None otherwiseis_alive(): Returns True if tiling is still runningjoin(timeout): Wait for tiling to complete
Note
Process-based tilers report progress as 0.0 (running) or 1.0 (complete),
since subprocess progress cannot be monitored incrementally. The
TilingHandle wraps the Future and provides a compatible interface
for integration with TiledMediaObject.
Process Isolation:
Tilers run in separate processes via ProcessPoolExecutor, providing complete isolation:
No threading conflicts with TileManager threads
Each pyvips instance runs in its own memory space
True parallel tiling (multiple images can be tiled simultaneously)
No deadlocks from pyvips internal threading
Integration with TiledMediaObject:
TiledMediaObject automatically uses process-based tiling via tilerrunner
when converting and tiling media files. The conversion and tiling pipeline is:
Converter runs in separate process via
converterrunnerOutput PPM file is passed to
tilerrunnerTiling runs in separate process
Progress is tracked across both conversion and tiling phases
TileStore¶
The TileStore module manages disk-based tile storage and metadata persistence.
Directory Structure:
Tiles are organized by media ID using SHA1 hashing:
~/.cache/zooui/tilestore/
└── <sha1_hash_of_media_id>/
├── metadata
├── 00/
│ └── 00_000000_000000.jpg
├── 01/
│ ├── 01_000000_000000.jpg
│ ├── 01_000000_000001.jpg
│ ├── 01_000001_000000.jpg
│ └── 01_000001_000001.jpg
└── 02/
└── ...
Tile Path Format:
<tilelevel>/<tilelevel>_<row>_<col>.<ext>
Where row and column are zero-padded to 6 digits.
Metadata File Format:
Tab-separated values with type information:
width 1024 int
height 768 int
tilesize 256 int
filext jpg str
maxtilelevel 2 int
Key Functions:
get_media_path(media_id): Get the directory for a media’s tilesget_tile_path(tile_id, filext, mkdirp, prefix): Get the file path for a specific tile.mkdirp=Truecreates parent directories (used by Tiler for output).prefixoverrides the media directory root (for custom output paths).load_metadata(media_id): Load metadata from disk into memory. Uses a lock-free fast path with double-check locking insidedisk_lockfor on-demand loading.get_metadata(media_id, key): Retrieve a metadata valuewrite_metadata(media_id, **kwargs): Write metadata to disktiled(media_id): Check if a media has been fully tiledget_tilestore_stats(): Get statistics about the tilestoreget_directory_size(path): Calculate total disk usage for a directorycleanup_old_tiles(max_age_days, dry_run): Remove old tile directories.dry_run=Truereports what would be deleted without actually removing files.auto_cleanup(max_age_days, enable, collect_stats): Automatic cleanup with statistics
Automatic Cleanup System:
The tilestore includes an automatic cleanup system that removes old tile directories to manage disk space. Cleanup runs on application shutdown by default to improve startup performance.
# Enable automatic cleanup (runs on shutdown by default)
tilemanager.init(auto_cleanup=True, cleanup_max_age_days=3)
# Disable automatic cleanup
tilemanager.init(auto_cleanup=False)
# Run cleanup manually
from zooui.tilesystem.tilestore import auto_cleanup
stats = auto_cleanup(max_age_days=3, enable=True, collect_stats=False)
Cleanup Behavior:
Shutdown Cleanup (default): Runs when application exits gracefully
Manual Cleanup: Can be triggered via command-line utility or
auto_cleanup()Statistics Collection: Can be disabled for faster cleanup
Cleanup Statistics:
When collect_stats=True, the cleanup process logs:
1. Before cleanup: Media count, file count, total size
2. Cleanup results: Deleted media, freed space, errors
3. After cleanup: Media count, file count, total size
When collect_stats=False (fast mode, default for shutdown), only cleanup
results are logged.
Command-line Options:
python main.py --no-cleanup # Disable cleanup entirely
python main.py --cleanup-age 30 # Clean tiles older than 30 days
python main.py --fast-cleanup # Skip detailed statistics
Standalone Cleanup CLI (cleanuptilestore)¶
The cleanuptilestore.py module provides a standalone CLI utility for manual
tilestore cleanup, runnable via:
python -m zooui.tilesystem.tilestore.cleanuptilestore --age 7 --stats --verbose
Command-line Options:
--age N Remove tiles older than N days (default: 3)
--dry-run Show what would be deleted without actually removing
--stats Collect and display before/after statistics
--verbose Enable detailed logging output
--debug Enable debug-level logging output
The utility initializes its own logger, runs cleanup_old_tiles() with the
specified options, and prints a formatted summary of the results.
TileCache¶
The TileCache class (at zooui/tilesystem/tilestore/tilecache.py) provides
in-memory LRU (Least Recently Used) caching of tiles.
Features:
Size-Based Eviction: Automatically evicts tiles when
maxsizeis exceededAge-Based Expiration: Optional
maxageparameter for time-based evictionAccess-Based Expiration: Tiles can expire after N accesses via
maxaccessesoninsert()Immortal Tiles: Level 0 tiles (overview) and
Nonevalues are never evicted. The__mortal()method returns True only when both the tile is not None ANDtile_id[1] != 0. This prevents both overview tiles and pending/loading slots from being discarded.Thread Safety: RLock protects concurrent access
Periodic Clean Daemon:
When maxage is set, TileCache spawns a daemon thread that wakes every
maxage / 3 seconds and evicts age-expired tiles. The daemon is controlled
via a threading.Event for clean shutdown:
# In TileCache.__init__():
self.__shutdown_event = threading.Event()
# Shutdown called by TileManager.shutdown():
def shutdown(self):
self.__shutdown_event.set() # Signal daemon to exit
The daemon thread checks the event each cycle and exits gracefully when signalled.
Insert Method:
The insert(tile_id, tile, maxaccesses=0) method adds a tile with optional
access-based expiration. When maxaccesses > 0, the tile is evicted after
the specified number of accesses (reads) to the tile. This is used by
cut_tile() with tempcache for synthesized tiles that can be regenerated.
None Tile Protection:
When __setitem__ attempts to set a tile_id that already holds a valid tile
to None, the operation is silently ignored. This prevents a failed tile
load from overwriting a previously cached valid tile.
Dual-Tier Caching:
The TileManager uses two caches:
Permanent Cache (80%): Stores tiles loaded from disk and procedurally generated tiles (e.g., FernTileProvider tiles go here)
Temporary Cache (20%): Stores synthesized/cut tiles that can be regenerated
TileManager¶
The TileManager module coordinates tile requests between providers and caches.
Initialization:
tilemanager.init(
total_cache_size=1024, # Total cache size in number of tiles
auto_cleanup=True, # Enable automatic cleanup
cleanup_max_age_days=3, # Remove tiles older than 3 days
collect_cleanup_stats=False # Skip detailed stats for faster startup
)
Key Functions:
load_tile(tile_id): Request a tile to be loaded (asynchronous)get_tile(tile_id): Get a tile from cache (raises if not available)get_tile_robust(tile_id): Get tile with fallback to synthesiscut_tile(tile_id): Synthesize a tile from parent tilestiled(media_id): Check if media is tiledget_metadata(media_id, key): Get metadata for a mediapurge(media_id=None): Remove tiles from providers and cache
Lifecycle Management:
init(): Initialize caches, start provider threads, register shutdown hookshutdown(): Stop all provider threads, stop cache clean daemon threads, run tilestore cleanup. Connected to Qt’saboutToQuitsignal.pause(): Pause all TileProvider threads. Used during process-based conversion whenPYZUI_MP_CONTEXT=forkis configured.resume(): Resume all paused TileProvider threads.
Pause/Resume Integration:
from zooui.tilesystem import tilemanager
# Before forking (if using PYZUI_MP_CONTEXT=fork)
tilemanager.pause()
# ... conversion in subprocess ...
# After forking completes
tilemanager.resume()
With the default 'spawn' process context, pause/resume is typically not
needed since spawn creates a fresh interpreter state. It exists primarily
for platforms or configurations where fork is required.
Tile Synthesis (cut_tile):
When a tile is not available, it can be synthesized from parent tiles:
Requested: (media, level=2, row=3, col=5)
Parent: (media, level=1, row=1, col=2)
Parent tile is cropped to the correct quadrant:
┌─────┬─────┐
│ 0,0 │ 0,1 │ ← row=3 is odd, col=5 is odd
├─────┼─────┤ so we take bottom-right quadrant
│ 1,0 │*1,1*│
└─────┴─────┘
Then resized to full tile dimensions.
Synthesized tiles are inserted into the temporary cache via insert(tile_id,
tile, maxaccesses=tempcache), limiting how many times they can be accessed
before being regenerated.
Negative Tile Levels:
Negative tile levels represent zoomed-out views beyond level 0:
Level -1: 50% of level 0
Level -2: 25% of level 0
etc.
get_tile() raises TileNotAvailable for negative tile levels. The
cut_tile() function handles them by resizing the (0,0,0) tile, so use
get_tile_robust() for transparent negative-level support.
TileProviders¶
Tile providers are responsible for loading or generating tiles.
Base Class: TileProvider
Abstract base class running as a daemon thread. Provides:
request(tile_id): Queue a tile load request (LIFO order)_load(tile_id): Abstract method to load/generate a tile (note: underscore-prefixed)purge(media_id=None): Cancel pending requestsstop(): Signal the provider thread to exitpause(): Pause processing of the task queue (used during forked conversions)resume(): Resume processing after a pause
Synchronization:
The provider uses three threading primitives beyond RLock:
threading.Condition: For the LIFO task queue — waiters are notified when new tasks arrivethreading.Event(pause): Blocks the run loop during pause, signalled byresume()threading.Event(shutdown): Signals the run loop to exit gracefully, set bystop()
StaticTileProvider
Loads pre-tiled images from the TileStore. On a cache miss, the provider
reads the tile from disk using PIL.Image.open() on the path returned by
TileStore.get_tile_path(), then stores it in the permanent cache.
Loading from disk is the only operation — StaticTileProvider does not
perform synthesis or re-save tiles. It returns None if the tile file
does not exist on disk.
DynamicTileProvider
Generates tiles procedurally. The only concrete subclass in the codebase is:
FernTileProvider: Barnsley fern fractal (atzooui/tilesystem/tileproviders/ferndynamictileprovider.py)
Dynamic provider tiles go to the permanent cache (like StaticProvider tiles), not the temporary cache.
Tile ID Format¶
A tile is identified by a 4-tuple:
(media_id, tilelevel, row, col)
media_id: String identifying the source image or dynamic content
tilelevel: Integer pyramid level (0 = overview, higher = more detail)
row: Integer row index (0-based, top to bottom)
col: Integer column index (0-based, left to right)
Examples:
("photo.jpg", 0, 0, 0): Overview tile of photo.jpg("photo.jpg", 2, 3, 5): Detail tile at level 2, row 3, column 5("dynamic:fern", 10, 512, 256): Procedurally generated fern tile
Tile Request Flow¶
The following sequence describes how a tile is requested and delivered:
1. Application requests tile via get_tile_robust(tile_id)
│
▼
2. TileManager checks permanent cache
├─ Cache HIT → Return tile
└─ Cache MISS → Continue
│
▼
3. TileManager routes to appropriate provider
├─ "dynamic:*" → DynamicTileProvider
└─ Otherwise → StaticTileProvider
│
▼
4. Provider loads/generates tile
├─ StaticTileProvider reads from TileStore
└─ DynamicTileProvider generates procedurally
│
▼
5. Tile is stored in cache
│
▼
6. Tile is returned to application
Fallback Synthesis:
If a tile is not available (TileNotLoaded/TileNotAvailable), the system
attempts to synthesize it from parent tiles via cut_tile().
Performance Considerations¶
Memory Management:
The cache uses approximately 80/20 split between permanent and temporary tiles (counted by number of tiles, default total: 1024)
LRU eviction prevents unbounded memory growth
Level 0 tiles and None values are immortal (always kept) as they’re frequently accessed or represent pending load slots
Disk I/O:
Tiles are loaded lazily on demand
LIFO queue prioritizes recently requested tiles
Disk lock prevents concurrent write conflicts
Threading:
TileProviders run as daemon threads
Condition variables and Events coordinate provider lifecycle
Tiler uses internal
ThreadPoolExecutorfor parallel row processingProcess-based tiling (tilerrunner) uses
ProcessPoolExecutorfor full isolation
Recommended Settings:
Cache Size: 1024 tiles (typical usage)
Tile Size: 256×256 for balance of overhead vs. granularity
Process Workers: 2 (default for tilerrunner)
Auto-Cleanup: Enable with 3-30 day retention for disk management - Runs on shutdown by default for faster startup - Use
--fast-cleanupto skip detailed statistics - Disable with--no-cleanupif not needed
Exception Handling¶
The tiling system defines three exception types:
MediaNotTiled
Raised when accessing a media that hasn’t been tiled yet:
try:
tile = tilemanager.get_tile(tile_id)
except MediaNotTiled:
# Need to tile the image first
start_tiling(media_path)
TileNotLoaded
Raised when a tile exists but isn’t in the cache yet:
try:
tile = tilemanager.get_tile(tile_id)
except TileNotLoaded:
# Request tile load and wait or use cut_tile
tilemanager.load_tile(tile_id)
TileNotAvailable
Raised when a tile cannot be loaded (file missing, error, or None in cache):
try:
tile = tilemanager.get_tile(tile_id)
except TileNotAvailable:
# Tile doesn't exist, synthesize from parent
tile = tilemanager.cut_tile(tile_id)[0]
Robust Access:
Use get_tile_robust() for automatic fallback handling:
tile = tilemanager.get_tile_robust(tile_id)
# Never raises TileNotLoaded or TileNotAvailable
Usage Examples¶
Tiling an Image (Process-Based, Recommended):
from zooui.tilesystem.tiler import tilerrunner
from zooui.tilesystem import tilestore, tilemanager
# Initialize the tilemanager
tilemanager.init(total_cache_size=1024, auto_cleanup=True,
cleanup_max_age_days=3)
# Submit tiling to process pool
future = tilerrunner.submit_tiling(
infile='image.ppm',
media_id='photo1',
filext='jpg',
tilesize=256,
)
handle = tilerrunner.TilingHandle(future, 'image.ppm', 'photo1')
handle.join()
if handle.error:
print(f"Tiling failed: {handle.error}")
else:
print(f"Tiled successfully: {tilestore.get_metadata('photo1', 'maxtilelevel')} levels")
# Shutdown when done with all tiling
tilerrunner.shutdown()
Pausing Providers (for fork-based conversions):
from zooui.tilesystem import tilemanager
# Pause all providers before forking
tilemanager.pause()
# ... run conversion in a fork-based subprocess ...
tilemanager.resume()
Retrieving Tiles:
# Request tiles for display
tile_id = ("photo1", 2, 0, 0)
# Ensure tile is loaded
tilemanager.load_tile(tile_id)
# Get tile (may need retry if loading is async)
try:
tile = tilemanager.get_tile(tile_id)
tile.draw(painter, x, y)
except TileNotLoaded:
# Show placeholder, tile is loading
pass
Working with Dynamic Content:
# Dynamic tiles are always "tiled"
assert tilemanager.tiled("dynamic:fern") == True
# Get procedurally generated tile
tile = tilemanager.get_tile_robust(("dynamic:fern", 10, 100, 200))
# Metadata for dynamic content
tilesize = tilemanager.get_metadata("dynamic:fern", "tilesize") # 256
maxlevel = tilemanager.get_metadata("dynamic:fern", "maxtilelevel") # 18
Manual Tilestore Cleanup:
# CLI utility
python -m zooui.tilesystem.tilestore.cleanuptilestore --age 30 --dry-run --stats
# Or programmatically
from zooui.tilesystem.tilestore import cleanup_old_tiles
cleanup_old_tiles(max_age_days=30, dry_run=True)
API Reference¶
For detailed API documentation, see:
../zooui/tile
../zooui/tiler
../zooui/tilerrunner
../zooui/tilestore
../zooui/tilecache
../zooui/tilemanager
../zooui/tileprovider
See Also¶
Tiled media object — TiledMediaObject implementation
Converter System — Media format conversion
Object System — Object system architecture