Reading PMTiles¶
This guide covers advanced topics for reading PMTiles archives.
Opening PMTiles Archives¶
PMTiles archives can be opened from any data source supported by Range Reader:
// Local file
RangeReader fileReader = FileRangeReader.builder()
.path(Path.of("tiles.pmtiles"))
.build();
// HTTP
RangeReader httpReader = HttpRangeReader.builder()
.uri(URI.create("https://example.com/tiles.pmtiles"))
.build();
// S3
RangeReader s3Reader = S3RangeReader.builder()
.uri(URI.create("s3://bucket/tiles.pmtiles"))
.build();
Reading Header Information¶
The header contains essential metadata about the tileset:
try (PMTilesReader reader = new PMTilesReader(rangeReader)) {
PMTilesHeader header = reader.getHeader();
// Tile format (MVT, PNG, JPEG, WEBP, etc.)
String tileType = header.tileType();
// Zoom level range
int minZoom = header.minZoom();
int maxZoom = header.maxZoom();
// Geographic bounds (in E7 format: degrees * 10,000,000)
double minLon = header.minLonE7() / 10_000_000.0;
double minLat = header.minLatE7() / 10_000_000.0;
double maxLon = header.maxLonE7() / 10_000_000.0;
double maxLat = header.maxLatE7() / 10_000_000.0;
System.out.printf("Bounds: [%.6f, %.6f, %.6f, %.6f]%n",
minLon, minLat, maxLon, maxLat);
}
Reading Individual Tiles¶
Tiles are retrieved using the standard Z/X/Y addressing:
Optional<byte[]> tileData = reader.getTile(zoom, x, y);
if (tileData.isPresent()) {
byte[] tile = tileData.get();
// Process tile data...
} else {
// Tile doesn't exist in the archive
}
Bulk Tile Operations¶
Reading a Tile Range¶
int zoom = 10;
for (int x = 880; x <= 890; x++) {
for (int y = 410; y <= 420; y++) {
Optional<byte[]> tile = reader.getTile(zoom, x, y);
if (tile.isPresent()) {
processTile(zoom, x, y, tile.get());
}
}
}
Parallel Processing¶
PMTilesReader is thread-safe for read operations:
IntStream.range(880, 891)
.parallel()
.forEach(x -> {
IntStream.range(410, 421).forEach(y -> {
reader.getTile(zoom, x, y).ifPresent(tile -> {
processTile(zoom, x, y, tile);
});
});
});
Performance Tips¶
- Use caching for cloud storage sources
- Enable block alignment for optimal read patterns
- Reuse readers instead of creating new instances
- Batch operations when processing multiple tiles
See Cloud Storage for detailed performance optimization strategies.
Error Handling¶
try (PMTilesReader reader = new PMTilesReader(rangeReader)) {
Optional<byte[]> tile = reader.getTile(zoom, x, y);
// Process tile...
} catch (UncheckedIOException e) {
// Handle I/O errors (network issues, file not found, etc.)
System.err.println("Failed to read PMTiles: " + e.getMessage());
} catch (Exception e) {
// Handle other errors (invalid format, etc.)
System.err.println("Error: " + e.getMessage());
}
Next Steps¶
- Writing PMTiles: Create your own PMTiles archives
- Cloud Storage: Optimize for cloud storage