mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 02:41:09 +00:00
Add intelligent overview selection for tif to pmtiles conversion (#601)
* load overviews instead of full detail to avoid memory bomb * fix overview level indexing & use None when no overview for clarity * tweak nodata value for RGBA
This commit is contained in:
committed by
GitHub
parent
5ef8559b8d
commit
82d53ea0a0
@@ -335,11 +335,12 @@ def pmtiles(
|
|||||||
warp_options["cutline"] = shapely.wkt.dumps(cutline_rev)
|
warp_options["cutline"] = shapely.wkt.dumps(cutline_rev)
|
||||||
|
|
||||||
# Resolve the minimum and maximum zoom levels for export.
|
# Resolve the minimum and maximum zoom levels for export.
|
||||||
|
maxzoom_in_file = guess_maxzoom(src.crs, src.bounds, src.width, src.height, tile_size)
|
||||||
if zoom_levels:
|
if zoom_levels:
|
||||||
minzoom, maxzoom = map(int, zoom_levels.split(".."))
|
minzoom, maxzoom = map(int, zoom_levels.split(".."))
|
||||||
else:
|
else:
|
||||||
minzoom = 0
|
minzoom = 0
|
||||||
maxzoom = guess_maxzoom(src.crs, src.bounds, src.width, src.height, tile_size)
|
maxzoom = maxzoom_in_file
|
||||||
|
|
||||||
log.debug("Zoom range: %d..%d", minzoom, maxzoom)
|
log.debug("Zoom range: %d..%d", minzoom, maxzoom)
|
||||||
|
|
||||||
@@ -358,7 +359,7 @@ def pmtiles(
|
|||||||
{
|
{
|
||||||
"driver": img_format.upper(),
|
"driver": img_format.upper(),
|
||||||
"dtype": "uint8",
|
"dtype": "uint8",
|
||||||
"nodata": 0,
|
"nodata": 255 if rgba else 0,
|
||||||
"height": tile_size,
|
"height": tile_size,
|
||||||
"width": tile_size,
|
"width": tile_size,
|
||||||
"count": count,
|
"count": count,
|
||||||
@@ -442,6 +443,7 @@ def pmtiles(
|
|||||||
warp_options,
|
warp_options,
|
||||||
creation_options,
|
creation_options,
|
||||||
exclude_empty_tiles,
|
exclude_empty_tiles,
|
||||||
|
maxzoom_in_file,
|
||||||
),
|
),
|
||||||
) as executor:
|
) as executor:
|
||||||
for tile, contents in executor.map(process_tile, unwrap_tiles(tiles)):
|
for tile, contents in executor.map(process_tile, unwrap_tiles(tiles)):
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ def init_worker(
|
|||||||
warp_opts=None,
|
warp_opts=None,
|
||||||
creation_opts=None,
|
creation_opts=None,
|
||||||
exclude_empties=True,
|
exclude_empties=True,
|
||||||
|
max_zoom=None,
|
||||||
):
|
):
|
||||||
global base_kwds, filename, resampling, open_options, warp_options, creation_options, exclude_empty_tiles
|
global base_kwds, filename, resampling, open_options, warp_options, creation_options, exclude_empty_tiles, max_zoom_level
|
||||||
resampling = Resampling[resampling_method]
|
resampling = Resampling[resampling_method]
|
||||||
base_kwds = profile.copy()
|
base_kwds = profile.copy()
|
||||||
filename = path
|
filename = path
|
||||||
@@ -34,6 +35,7 @@ def init_worker(
|
|||||||
warp_options = warp_opts.copy() if warp_opts is not None else {}
|
warp_options = warp_opts.copy() if warp_opts is not None else {}
|
||||||
creation_options = creation_opts.copy() if creation_opts is not None else {}
|
creation_options = creation_opts.copy() if creation_opts is not None else {}
|
||||||
exclude_empty_tiles = exclude_empties
|
exclude_empty_tiles = exclude_empties
|
||||||
|
max_zoom_level = max_zoom
|
||||||
|
|
||||||
|
|
||||||
def process_tile(tile):
|
def process_tile(tile):
|
||||||
@@ -54,7 +56,28 @@ def process_tile(tile):
|
|||||||
Image bytes corresponding to the tile.
|
Image bytes corresponding to the tile.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
global base_kwds, resampling, filename, open_options, warp_options, creation_options, exclude_empty_tiles
|
global base_kwds, resampling, filename, open_options, warp_options, creation_options, exclude_empty_tiles, max_zoom_level
|
||||||
|
|
||||||
|
# Determine overview level to use
|
||||||
|
temp_src = rasterio.open(filename)
|
||||||
|
overviews = temp_src.overviews(1)
|
||||||
|
temp_src.close()
|
||||||
|
overview_level = None
|
||||||
|
if overviews and tile.z < max_zoom_level:
|
||||||
|
OVERSAMPLING_FACTOR = 4 # oversampling factor to ensure sufficient pixels for resampling operations
|
||||||
|
target_factor = 2 ** (max_zoom_level - tile.z) / OVERSAMPLING_FACTOR
|
||||||
|
best_overview = overview_level
|
||||||
|
best_score = float("inf")
|
||||||
|
for i_overview, factor in enumerate(overviews):
|
||||||
|
if factor <= target_factor:
|
||||||
|
score = abs(factor - target_factor)
|
||||||
|
if score < best_score:
|
||||||
|
best_score = score
|
||||||
|
best_overview = i_overview
|
||||||
|
overview_level = best_overview
|
||||||
|
|
||||||
|
if overview_level is not None:
|
||||||
|
open_options["OVERVIEW_LEVEL"] = overview_level
|
||||||
|
|
||||||
with rasterio.open(filename, **open_options) as src:
|
with rasterio.open(filename, **open_options) as src:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user