Tessera (tessera v0.2.0)

Copy Markdown View Source

Tessera is the DZI deep-zoom + multi-layer progressive-quality layer for Fresco-based image viewers in Phoenix.

Two pieces

  • Server side (unchanged from 0.1): generate DZI tile pyramids from images, eagerly or lazily on demand.

  • Client side: a Fresco layer that registers a DZI source provider and a multi-layer source-swap.

    • Tessera.layer/1<Tessera.layer fresco_id sources>, attaches to a <Fresco.viewer id> by id.

Quick start

Generate tiles server-side (any time — at upload, lazily, etc.):

{:ok, %{manifest: manifest, tiles_dir: _}} =
  Tessera.generate("/uploads/photo.jpg", "/var/www/dzi")

Render in a LiveView — a Fresco viewer that auto-handles DZI sources via Tessera, with multi-layer progressive zoom from a cheap preview to the deep-zoom pyramid:

~H"""
<Fresco.viewer
  id="photo"
  src={~p"/uploads/photo-medium.jpg"}
  class="w-full h-[80vh] rounded"
/>

<Tessera.layer
  fresco_id="photo"
  sources={[
    %{url: ~p"/uploads/photo-medium.jpg", width: 1024},
    %{url: ~p"/uploads/photo-large.jpg",  width: 2560},
    %{url: ~p"/dzi/photo.dzi"}
  ]}
/>
"""

Tessera's JS hook attaches to the named Fresco viewer, watches zoom events, and swaps between layers when the user's zoom crosses each threshold — keeping medium → large → DZI as a smooth ladder rather than a single jump.

What changed in 0.2

Tessera 0.1 was a standalone viewer (<Tessera.viewer>). In 0.2 it's a Fresco layer (<Tessera.layer fresco_id=...>) instead. The Fresco viewer owns the OSD instance, the nav overlay, the smooth animations, and the viewport clamping. Tessera contributes:

  • A DZI source provider registered with Fresco
  • The multi-layer progressive-zoom logic (debounced, hysteresis)

The server-side Tessera.generate/3 etc. API is unchanged. Existing consumers of the Elixir-side generators don't need to update anything on the server.

Requires magick (ImageMagick) on the host PATH for tile generation, and Fresco + Tessera JS wired into the parent app's LiveSocket hooks (see the README).

See also

Summary

Functions

generate(input_path, output_dir, opts \\ [])

See Tessera.TileGenerator.generate/3.

generate_manifest(dimensions, base_name, opts \\ [])

See Tessera.TileGenerator.generate_manifest/3.

generate_tile(input_path, coord, base_name, opts)

See Tessera.TileGenerator.generate_tile/4.

layer(assigns)

See Tessera.Layer.layer/1.