Skip to main content

Crate bevy_deepzoom

Crate bevy_deepzoom 

Source
Expand description

Deep Zoom image rendering for 2D Bevy scenes.

bevy_deepzoom allows streaming Deep Zoom Image (DZI) pyramids into Bevy scenes by attaching DeepZoom components to Camera2d entities.

§Quick start

Add DeepZoomPlugin to your app and a DeepZoom component to your Camera2d.

use bevy::prelude::*;
use bevy_deepzoom::{DeepZoom, DeepZoomConfig, DeepZoomInitialView, DeepZoomPlugin};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(DeepZoomPlugin)
        .add_systems(Startup, spawn_camera)
        .run();
}

fn spawn_camera(mut commands: Commands) {
    let config = DeepZoomConfig::new("assets/map/tiles.dzi", "assets/map/tiles_files")
        .with_initial_view(DeepZoomInitialView::FitWidth)
        .with_zoom_level_bias(1)
        .with_max_concurrent_tile_loads(8);

    commands.spawn((
        Camera2d,
        DeepZoom::from_config(config),
    ));
}

The plugin

  • loads the .dzi manifest
  • derives the required tile zoom level from the camera projection scale
  • streams in visible tiles for that level
  • despawns tiles that are out of view or too high res for the camera scale
  • clean up tiles when their owning camera is removed

§Asset layout

bevy_deepzoom expects a .dzi manifest and matching tile directory, typically:

assets/map/tiles.dzi
assets/map/tiles_files/
assets/map/tiles_files/0/0_0.jpeg
assets/map/tiles_files/1/0_0.jpeg
assets/map/tiles_files/8/12_4.jpeg

§Generating a pyramid from a source image

To create new DZI assets, libvips dzsave works well. e.g.:

vips dzsave "source.png" "tiles" \
  --layout dz \
  --tile-size 256 \
  --overlap 0 \
  --depth onepixel \
  --suffix ".jpeg[Q=90]"

§Pyramid depth

DeepZoomPyramidDepth should be set based on the libvips dzsave --depth ... value used when generating the DZI assets.

§Tuning sharpness and request volume

DeepZoomConfig::with_zoom_level_bias controls how aggressively the viewer prefers sharper tiles. A higher value loads higher-resolution levels sooner.

DeepZoomConfig::with_max_concurrent_tile_loads limits how many tile loads are allowed to be in flight for a viewer at once. Reduce this if you get rate limited or experience performance issues when loading many tiles in parallel.

§Events

Use DeepZoomLoaded to run app-specific setup once the .dzi is loaded. Use DeepZoomLoadFailed to react to failed loads.

use bevy::prelude::*;
use bevy_deepzoom::{DeepZoomLoadFailed, DeepZoomLoaded};

fn on_deepzoom_loaded(
    loaded: On<DeepZoomLoaded>,
    mut cameras: Query<&mut Transform, With<Camera2d>>,
) {
    let Ok(mut transform) = cameras.get_mut(loaded.event().0) else {
        return;
    };

    transform.translation.z = 10.0;
}

fn on_deepzoom_load_failed(failed: On<DeepZoomLoadFailed>) {
    let entity = failed.event().0;
    let reason = &failed.event().1;
}

Modules§

dzi_asset_loader
Loader for the .dzi file format.

Structs§

DeepZoom
Attach this to a Camera2d entity.
DeepZoomConfig
DeepZoomLoadFailed
Triggered when a .dzi manifest fails to load.
DeepZoomLoaded
Triggered when a .dzi manifest finishes loading.
DeepZoomPlugin

Enums§

DeepZoomInitialView
DeepZoomLoadState
DeepZoomPyramidDepth

Constants§

DEFAULT_MAX_CONCURRENT_TILE_LOADS
Default maximum number of concurrent in-flight tile loads.
DEFAULT_ZOOM_LEVEL_BIAS
Default number of zoom levels to bias toward sharper tiles.

Functions§

fit_width_scale
Computes the Camera2d scale required to fit the full image width in view.
loaded_dzi
Returns the loaded .dzi.

Type Aliases§

TileId
(zoom_level, x, y) identifier for a tile.