napari-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/cache/lru.d.ts +19 -0
  4. package/dist/camera/camera.d.ts +25 -0
  5. package/dist/camera/camera3d.d.ts +28 -0
  6. package/dist/camera/controls.d.ts +7 -0
  7. package/dist/camera/controls3d.d.ts +6 -0
  8. package/dist/color/checkerboard.d.ts +5 -0
  9. package/dist/color/colormap.d.ts +26 -0
  10. package/dist/color/display-pipeline.d.ts +22 -0
  11. package/dist/color/histogram.d.ts +14 -0
  12. package/dist/color/label-colormap.d.ts +7 -0
  13. package/dist/color/lut.d.ts +9 -0
  14. package/dist/engine/canvas.d.ts +20 -0
  15. package/dist/engine/device.d.ts +23 -0
  16. package/dist/engine/readback.d.ts +13 -0
  17. package/dist/engine/renderer.d.ts +42 -0
  18. package/dist/engine/viewport.d.ts +12 -0
  19. package/dist/index.d.ts +34 -0
  20. package/dist/io/pyramid.d.ts +41 -0
  21. package/dist/io/texture-source.d.ts +68 -0
  22. package/dist/layers/image-layer.d.ts +47 -0
  23. package/dist/layers/labels-layer.d.ts +32 -0
  24. package/dist/layers/layer.d.ts +32 -0
  25. package/dist/layers/points-layer.d.ts +59 -0
  26. package/dist/layers/volume-layer.d.ts +46 -0
  27. package/dist/math/mat4.d.ts +22 -0
  28. package/dist/napari-js.js +1986 -0
  29. package/dist/napari-js.js.map +1 -0
  30. package/dist/picking/pick.d.ts +6 -0
  31. package/dist/scene/dims.d.ts +20 -0
  32. package/dist/scene/events.d.ts +9 -0
  33. package/dist/scene/layer-list.d.ts +16 -0
  34. package/dist/scene/viewer-model.d.ts +20 -0
  35. package/dist/version.d.ts +1 -0
  36. package/dist/viewer.d.ts +76 -0
  37. package/dist/visuals/blend.d.ts +6 -0
  38. package/dist/visuals/format-plan.d.ts +19 -0
  39. package/dist/visuals/image-colormap-shader.d.ts +1 -0
  40. package/dist/visuals/image-visual.d.ts +45 -0
  41. package/dist/visuals/labels-shader.d.ts +1 -0
  42. package/dist/visuals/labels-visual.d.ts +23 -0
  43. package/dist/visuals/layer-visual.d.ts +23 -0
  44. package/dist/visuals/points-shader.d.ts +1 -0
  45. package/dist/visuals/points-visual.d.ts +22 -0
  46. package/dist/visuals/tiled-image-visual.d.ts +46 -0
  47. package/dist/visuals/volume-shader.d.ts +1 -0
  48. package/dist/visuals/volume-visual.d.ts +32 -0
  49. package/package.json +60 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"napari-js.js","sources":["../src/engine/device.ts","../src/engine/viewport.ts","../src/engine/canvas.ts","../src/scene/events.ts","../src/layers/layer.ts","../src/color/colormap.ts","../src/io/texture-source.ts","../src/layers/image-layer.ts","../src/layers/points-layer.ts","../src/layers/labels-layer.ts","../src/layers/volume-layer.ts","../src/math/mat4.ts","../src/color/lut.ts","../src/visuals/format-plan.ts","../src/visuals/image-colormap-shader.ts","../src/visuals/blend.ts","../src/visuals/image-visual.ts","../src/io/pyramid.ts","../src/cache/lru.ts","../src/visuals/tiled-image-visual.ts","../src/visuals/points-shader.ts","../src/visuals/points-visual.ts","../src/color/label-colormap.ts","../src/visuals/labels-shader.ts","../src/visuals/labels-visual.ts","../src/visuals/volume-shader.ts","../src/visuals/volume-visual.ts","../src/engine/renderer.ts","../src/scene/layer-list.ts","../src/scene/dims.ts","../src/camera/camera.ts","../src/camera/camera3d.ts","../src/scene/viewer-model.ts","../src/camera/controls.ts","../src/camera/controls3d.ts","../src/engine/readback.ts","../src/color/histogram.ts","../src/viewer.ts","../src/picking/pick.ts","../src/color/display-pipeline.ts","../src/version.ts"],"sourcesContent":["/** GPU features napari-js opts into when the adapter supports them. */\nexport interface DeviceFeatures {\n /** Linear filtering of `r32float` textures (else 16-bit/float layers fall back to nearest). */\n float32Filterable: boolean;\n}\n\n/** A live WebGPU adapter + device pair plus the negotiated optional features. */\nexport interface DeviceContext {\n adapter: GPUAdapter;\n device: GPUDevice;\n features: DeviceFeatures;\n}\n\n/** Thrown when WebGPU is unavailable or no adapter/device can be obtained. */\nexport class WebGPUUnsupportedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebGPUUnsupportedError';\n }\n}\n\n/**\n * Acquire a WebGPU device, opting into `float32-filterable` when available. Throws\n * {@link WebGPUUnsupportedError} with an actionable message when the environment lacks\n * `navigator.gpu`, has no suitable adapter, or device creation fails.\n */\nexport async function acquireDevice(\n options: { powerPreference?: GPUPowerPreference } = {},\n): Promise<DeviceContext> {\n if (typeof navigator === 'undefined' || !('gpu' in navigator) || !navigator.gpu) {\n throw new WebGPUUnsupportedError(\n 'WebGPU is not available in this environment (navigator.gpu is missing).',\n );\n }\n const adapter = await navigator.gpu.requestAdapter({\n powerPreference: options.powerPreference ?? 'high-performance',\n });\n if (!adapter) {\n throw new WebGPUUnsupportedError('No suitable GPUAdapter was found.');\n }\n\n const float32Filterable = adapter.features.has('float32-filterable');\n const requiredFeatures: GPUFeatureName[] = float32Filterable ? ['float32-filterable'] : [];\n\n try {\n const device = await adapter.requestDevice({ requiredFeatures });\n return { adapter, device, features: { float32Filterable } };\n } catch (cause) {\n throw new WebGPUUnsupportedError(\n `Failed to create a GPUDevice: ${cause instanceof Error ? cause.message : String(cause)}`,\n );\n }\n}\n","/**\n * Resolve the backing drawing-buffer size from a canvas's CSS size and the device pixel\n * ratio, clamped to the GPU's maximum 2D texture dimension. Pure and GPU-free so it can be\n * unit-tested directly.\n *\n * - Non-positive `devicePixelRatio` falls back to 1.\n * - Each dimension is clamped to `[1, maxDimension]` and rounded to an integer.\n */\nexport function resolveDrawingBufferSize(\n cssWidth: number,\n cssHeight: number,\n devicePixelRatio: number,\n maxDimension: number,\n): { width: number; height: number } {\n const dpr = devicePixelRatio > 0 ? devicePixelRatio : 1;\n return {\n width: clampDim(Math.round(cssWidth * dpr), maxDimension),\n height: clampDim(Math.round(cssHeight * dpr), maxDimension),\n };\n}\n\nfunction clampDim(value: number, max: number): number {\n if (!Number.isFinite(value) || value < 1) return 1;\n return Math.min(value, Math.max(1, max));\n}\n","import { resolveDrawingBufferSize } from './viewport';\n\n/**\n * Owns a canvas's WebGPU context: format negotiation, configuration, and DPR-aware sizing.\n * The render loop reads {@link view} each frame for the current swapchain texture.\n */\nexport class CanvasTarget {\n readonly context: GPUCanvasContext;\n readonly format: GPUTextureFormat;\n\n constructor(\n readonly canvas: HTMLCanvasElement,\n readonly device: GPUDevice,\n format?: GPUTextureFormat,\n ) {\n const ctx = canvas.getContext('webgpu');\n if (!ctx) {\n throw new Error('Failed to acquire a \"webgpu\" canvas context.');\n }\n this.context = ctx;\n this.format = format ?? navigator.gpu.getPreferredCanvasFormat();\n this.configure();\n }\n\n /** (Re)configure the swapchain for the current device/format. */\n configure(): void {\n this.context.configure({\n device: this.device,\n format: this.format,\n alphaMode: 'premultiplied',\n });\n }\n\n /**\n * Resize the backing buffer to match the canvas's CSS size × DPR, clamped to the device's\n * max texture dimension. Returns `true` when the size actually changed.\n */\n syncSize(dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1): boolean {\n const maxDim = this.device.limits.maxTextureDimension2D;\n const { width, height } = resolveDrawingBufferSize(\n this.canvas.clientWidth,\n this.canvas.clientHeight,\n dpr,\n maxDim,\n );\n if (this.canvas.width === width && this.canvas.height === height) {\n return false;\n }\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n /** The current swapchain texture view for this frame. */\n get view(): GPUTextureView {\n return this.context.getCurrentTexture().createView();\n }\n}\n","export type Listener<T> = (value: T) => void;\n\n/** Minimal typed event emitter (the napari `EventEmitter` / psygnal analog). */\nexport class Emitter<T> {\n private readonly listeners = new Set<Listener<T>>();\n\n /** Subscribe; returns an unsubscribe function. */\n connect(listener: Listener<T>): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n emit(value: T): void {\n for (const listener of this.listeners) {\n listener(value);\n }\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","import { Emitter } from '../scene/events';\n\nexport type BlendMode = 'opaque' | 'translucent' | 'additive' | 'minimum';\n\nlet nextLayerId = 0;\n\n/**\n * Base layer: identity + the display properties shared by every layer kind (opacity,\n * blending, visibility, and a data→world affine via `scale`/`translate`). Mutating any\n * property emits {@link changed} so the renderer can schedule a redraw — the napari\n * evented-layer model, GPU-side.\n */\nexport abstract class Layer {\n readonly id: string = `layer-${nextLayerId++}`;\n readonly changed = new Emitter<Layer>();\n\n abstract readonly kind: string;\n\n name: string;\n\n /** Data→world scale (e.g. physical pixel size). */\n scale: [number, number];\n /** Data→world translation. */\n translate: [number, number];\n\n protected _opacity = 1;\n protected _visible = true;\n protected _blending: BlendMode = 'translucent';\n\n protected constructor(\n opts: {\n name?: string;\n scale?: [number, number];\n translate?: [number, number];\n } = {},\n ) {\n this.name = opts.name ?? this.id;\n this.scale = opts.scale ?? [1, 1];\n this.translate = opts.translate ?? [0, 0];\n }\n\n get opacity(): number {\n return this._opacity;\n }\n set opacity(value: number) {\n this._opacity = clamp01(value);\n this.changed.emit(this);\n }\n\n get visible(): boolean {\n return this._visible;\n }\n set visible(value: boolean) {\n this._visible = value;\n this.changed.emit(this);\n }\n\n get blending(): BlendMode {\n return this._blending;\n }\n set blending(value: BlendMode) {\n this._blending = value;\n this.changed.emit(this);\n }\n}\n\nfunction clamp01(v: number): number {\n return v < 0 ? 0 : v > 1 ? 1 : v;\n}\n","export type RGB = [number, number, number];\n\n/** A control point in a colormap: normalized position `t` (0..1) → linear RGB (0..1). */\nexport interface ColorStop {\n t: number;\n color: RGB;\n}\n\n/**\n * A colormap defined by sorted control points, linearly interpolated. Mirrors napari's\n * `Colormap` concept; sampled into a LUT texture for the GPU (see ./lut.ts).\n */\nexport class Colormap {\n readonly stops: ColorStop[];\n\n constructor(\n readonly name: string,\n stops: ColorStop[],\n ) {\n if (stops.length < 2) {\n throw new Error(`Colormap \"${name}\" needs at least two stops.`);\n }\n this.stops = [...stops].sort((p, q) => p.t - q.t);\n }\n\n /** Sample the colormap at `t` (clamped to 0..1), returning linear RGB. */\n sample(t: number): RGB {\n const x = t <= 0 ? 0 : t >= 1 ? 1 : t;\n const { stops } = this;\n if (x <= stops[0].t) return [...stops[0].color];\n const last = stops[stops.length - 1];\n if (x >= last.t) return [...last.color];\n for (let i = 1; i < stops.length; i++) {\n const hi = stops[i];\n if (x <= hi.t) {\n const lo = stops[i - 1];\n const span = hi.t - lo.t || 1;\n const f = (x - lo.t) / span;\n return [\n lo.color[0] + (hi.color[0] - lo.color[0]) * f,\n lo.color[1] + (hi.color[1] - lo.color[1]) * f,\n lo.color[2] + (hi.color[2] - lo.color[2]) * f,\n ];\n }\n }\n return [...last.color];\n }\n}\n\nfunction ramp(name: string, color: RGB): Colormap {\n return new Colormap(name, [\n { t: 0, color: [0, 0, 0] },\n { t: 1, color },\n ]);\n}\n\n// Single-hue ramps (napari's red/green/blue/gray).\nexport const GRAY = ramp('gray', [1, 1, 1]);\nexport const RED = ramp('red', [1, 0, 0]);\nexport const GREEN = ramp('green', [0, 1, 0]);\nexport const BLUE = ramp('blue', [0, 0, 1]);\n\n// Compact perceptual maps (a handful of anchors, interpolated).\nexport const VIRIDIS = new Colormap('viridis', [\n { t: 0.0, color: [0.267, 0.005, 0.329] },\n { t: 0.25, color: [0.275, 0.227, 0.494] },\n { t: 0.5, color: [0.149, 0.443, 0.541] },\n { t: 0.75, color: [0.122, 0.633, 0.531] },\n { t: 0.9, color: [0.478, 0.821, 0.318] },\n { t: 1.0, color: [0.993, 0.906, 0.144] },\n]);\n\nexport const MAGMA = new Colormap('magma', [\n { t: 0.0, color: [0.001, 0.0, 0.014] },\n { t: 0.25, color: [0.232, 0.059, 0.437] },\n { t: 0.5, color: [0.55, 0.161, 0.506] },\n { t: 0.75, color: [0.868, 0.288, 0.41] },\n { t: 0.9, color: [0.987, 0.6, 0.392] },\n { t: 1.0, color: [0.987, 0.991, 0.749] },\n]);\n\nexport const NAMED_COLORMAPS: Record<string, Colormap> = {\n gray: GRAY,\n grey: GRAY,\n red: RED,\n green: GREEN,\n blue: BLUE,\n viridis: VIRIDIS,\n magma: MAGMA,\n};\n\n/** Resolve a colormap name or pass through a `Colormap`. Throws on an unknown name. */\nexport function resolveColormap(cmap: Colormap | string): Colormap {\n if (cmap instanceof Colormap) return cmap;\n const found = NAMED_COLORMAPS[cmap.toLowerCase()];\n if (!found) {\n throw new Error(\n `Unknown colormap \"${cmap}\". Known: ${Object.keys(NAMED_COLORMAPS).join(', ')}.`,\n );\n }\n return found;\n}\n","/**\n * Pixel ingestion for NJ-1: a single full-resolution image (no tiling — that arrives in\n * NJ-3 as a pyramidal `TiledSource`). A source is either raw typed-array pixels or an\n * external decoded image (ImageBitmap/canvas) uploaded via `copyExternalImageToTexture`.\n */\n\nexport type PixelDtype = 'uint8' | 'uint16' | 'float32';\n\n/**\n * Raw scalar/RGBA pixels in a typed array. `uint8` → `r8unorm`/`rgba8unorm`;\n * `uint16`/`float32` scalar → `r32float` (native-precision windowing). RGBA is `uint8` only.\n */\nexport interface TypedImageSource {\n readonly kind: 'typed';\n readonly width: number;\n readonly height: number;\n readonly channels: 1 | 4;\n readonly dtype: PixelDtype;\n readonly data: Uint8Array | Uint16Array | Float32Array;\n}\n\n/** A decoded image to upload directly to an RGBA8 texture. */\nexport interface ExternalImageSource {\n readonly kind: 'external';\n readonly width: number;\n readonly height: number;\n readonly image: ImageBitmap | HTMLCanvasElement | OffscreenCanvas | HTMLImageElement;\n}\n\n/** Identifies one tile within a pyramidal/tiled source. */\nexport interface TileKey {\n /** Pyramid level (0 = full resolution; each level halves resolution). */\n level: number;\n col: number;\n row: number;\n /** Z-slice (0 when not a stack). */\n z: number;\n}\n\n/** Pixels for one tile. Edge tiles may be smaller than the nominal `tileSize`. */\nexport interface PixelChunk {\n width: number;\n height: number;\n data: Uint8Array | Uint16Array | Float32Array;\n}\n\n/**\n * A pyramidal, tiled, optionally z-stacked image — the general large-image case (whole-slide\n * microscopy etc.). `width`/`height` are full-resolution (level 0). Tiles are fetched lazily\n * via {@link fetchTile} and cached on the GPU. The host supplies `fetchTile` (e.g. a server\n * `/tile` request); napari-js stays ignorant of any backend.\n */\nexport interface TiledSource {\n readonly kind: 'tiled';\n readonly width: number;\n readonly height: number;\n readonly tileSize: number;\n readonly levels: number;\n readonly depth: number;\n readonly channels: 1 | 4;\n readonly dtype: PixelDtype;\n fetchTile(key: TileKey): Promise<PixelChunk>;\n}\n\nexport type TextureSource = TypedImageSource | ExternalImageSource | TiledSource;\n\n/** Anything `Viewer.addImage` accepts. */\nexport type ImageInput =\n | TypedImageSource\n | TiledSource\n | ImageBitmap\n | HTMLCanvasElement\n | HTMLImageElement;\n\nexport function channelsOf(source: TextureSource): 1 | 4 {\n return source.kind === 'typed' || source.kind === 'tiled' ? source.channels : 4;\n}\n\n/** Number of z-slices in a source (1 unless it's a z-stacked tiled source). */\nexport function depthOf(source: TextureSource): number {\n return source.kind === 'tiled' ? source.depth : 1;\n}\n\nexport function isGrayscale(source: TextureSource): boolean {\n return channelsOf(source) === 1;\n}\n\n/** Default contrast-limit window for a source, in source-data units. */\nexport function defaultContrastLimits(source: TextureSource): [number, number] {\n if (source.kind === 'typed' || source.kind === 'tiled') {\n if (source.dtype === 'float32') return [0, 1];\n if (source.dtype === 'uint16') return [0, 65535];\n }\n return [0, 255];\n}\n\n/** Normalize a user input into a {@link TextureSource}. */\nexport function toTextureSource(input: ImageInput): TextureSource {\n if (\n typeof input === 'object' &&\n 'kind' in input &&\n (input.kind === 'typed' || input.kind === 'tiled')\n ) {\n return input;\n }\n const image = input as ImageBitmap | HTMLCanvasElement | HTMLImageElement;\n const width = 'width' in image ? Number(image.width) : 0;\n const height = 'height' in image ? Number(image.height) : 0;\n return { kind: 'external', width, height, image };\n}\n","import { Layer, type BlendMode } from './layer';\nimport { Colormap, resolveColormap } from '../color/colormap';\nimport { type TextureSource, defaultContrastLimits, isGrayscale } from '../io/texture-source';\n\nexport type Interpolation = 'nearest' | 'linear';\n\nexport interface ImageLayerOptions {\n name?: string;\n /** Scalar colormap; ignored for RGB(A) sources (rendered directly). Defaults to gray. */\n colormap?: Colormap | string;\n /** Normalization window in source-data units. Defaults to the source's dtype range. */\n contrastLimits?: [number, number];\n gamma?: number;\n invert?: boolean;\n opacity?: number;\n blending?: BlendMode;\n visible?: boolean;\n interpolation?: Interpolation;\n scale?: [number, number];\n translate?: [number, number];\n}\n\n/**\n * A 2D image layer. Carries the source pixels plus the scalar display pipeline\n * (contrast/gamma/invert/colormap). Display setters are reactive; changing them updates GPU\n * uniforms/LUT — never re-uploads the texture (tracked via {@link colormapVersion}).\n */\nexport class ImageLayer extends Layer {\n readonly kind = 'image';\n readonly source: TextureSource;\n readonly grayscale: boolean;\n\n /** Bumped whenever the colormap changes so the visual knows to rebuild its LUT. */\n colormapVersion = 0;\n\n private _colormap: Colormap | null;\n private _contrastLimits: [number, number];\n private _gamma: number;\n private _invert: boolean;\n private _interpolation: Interpolation;\n\n constructor(source: TextureSource, opts: ImageLayerOptions = {}) {\n super({ name: opts.name, scale: opts.scale, translate: opts.translate });\n this.source = source;\n this.grayscale = isGrayscale(source);\n this._colormap = this.grayscale ? resolveColormap(opts.colormap ?? 'gray') : null;\n this._contrastLimits = opts.contrastLimits ?? defaultContrastLimits(source);\n this._gamma = opts.gamma ?? 1;\n this._invert = opts.invert ?? false;\n this._interpolation = opts.interpolation ?? 'linear';\n if (opts.opacity !== undefined) this._opacity = opts.opacity;\n if (opts.blending !== undefined) this._blending = opts.blending;\n if (opts.visible !== undefined) this._visible = opts.visible;\n }\n\n get colormap(): Colormap | null {\n return this._colormap;\n }\n set colormap(value: Colormap | string | null) {\n // RGB(A) layers ignore colormaps (rendered directly).\n this._colormap = value === null ? null : this.grayscale ? resolveColormap(value) : null;\n this.colormapVersion++;\n this.changed.emit(this);\n }\n\n get contrastLimits(): [number, number] {\n return [this._contrastLimits[0], this._contrastLimits[1]];\n }\n set contrastLimits(value: readonly [number, number]) {\n this._contrastLimits = [value[0], value[1]];\n this.changed.emit(this);\n }\n\n get gamma(): number {\n return this._gamma;\n }\n set gamma(value: number) {\n this._gamma = value > 0 ? value : this._gamma;\n this.changed.emit(this);\n }\n\n get invert(): boolean {\n return this._invert;\n }\n set invert(value: boolean) {\n this._invert = value;\n this.changed.emit(this);\n }\n\n get interpolation(): Interpolation {\n return this._interpolation;\n }\n set interpolation(value: Interpolation) {\n this._interpolation = value;\n this.changed.emit(this);\n }\n}\n","import { Layer, type BlendMode } from './layer';\n\nexport type PointSymbol = 'disc' | 'ring' | 'square';\nexport type RGBA = [number, number, number, number];\n\n/** Per-point or broadcast scalar/color inputs. */\ntype SizeInput = number | number[] | Float32Array;\ntype ColorInput = RGBA | RGBA[];\n\nexport interface PointsLayerOptions {\n name?: string;\n /** Marker diameter in data units (single value or per-point). */\n size?: SizeInput;\n /** Fill color (single RGBA 0..1 or per-point). */\n faceColor?: ColorInput;\n /** Border color (single or per-point). */\n borderColor?: ColorInput;\n /** Border thickness in data units. */\n borderWidth?: number;\n symbol?: PointSymbol;\n opacity?: number;\n blending?: BlendMode;\n visible?: boolean;\n scale?: [number, number];\n translate?: [number, number];\n}\n\nconst STRIDE = 12; // x, y, size, fr,fg,fb,fa, br,bg,bb,ba, borderWidth\n\nfunction normalizePositions(positions: Float32Array | number[][]): Float32Array {\n if (positions instanceof Float32Array) return positions;\n const out = new Float32Array(positions.length * 2);\n positions.forEach((p, i) => {\n out[i * 2] = p[0];\n out[i * 2 + 1] = p[1];\n });\n return out;\n}\n\n/**\n * A scatter layer of point markers (the napari Points layer analog). Positions are `[x, y]`\n * pairs in data coordinates; size/colors may be uniform or per-point. Marker shape is one of\n * {@link PointSymbol}. Mutating display props emits `changed`; structural changes\n * (positions/size/colors) also bump {@link dataVersion} so the visual rebuilds its instance\n * buffer.\n */\nexport class PointsLayer extends Layer {\n readonly kind = 'points';\n readonly count: number;\n positions: Float32Array;\n dataVersion = 0;\n\n private _size: SizeInput;\n private _faceColor: ColorInput;\n private _borderColor: ColorInput;\n private _borderWidth: number;\n private _symbol: PointSymbol;\n\n constructor(positions: Float32Array | number[][], opts: PointsLayerOptions = {}) {\n super({ name: opts.name, scale: opts.scale, translate: opts.translate });\n this.positions = normalizePositions(positions);\n this.count = this.positions.length / 2;\n this._size = opts.size ?? 10;\n this._faceColor = opts.faceColor ?? [1, 1, 1, 1];\n this._borderColor = opts.borderColor ?? [0, 0, 0, 1];\n this._borderWidth = opts.borderWidth ?? 0;\n this._symbol = opts.symbol ?? 'disc';\n if (opts.opacity !== undefined) this._opacity = opts.opacity;\n if (opts.blending !== undefined) this._blending = opts.blending;\n if (opts.visible !== undefined) this._visible = opts.visible;\n }\n\n get size(): SizeInput {\n return this._size;\n }\n set size(value: SizeInput) {\n this._size = value;\n this.dataVersion++;\n this.changed.emit(this);\n }\n\n get faceColor(): ColorInput {\n return this._faceColor;\n }\n set faceColor(value: ColorInput) {\n this._faceColor = value;\n this.dataVersion++;\n this.changed.emit(this);\n }\n\n get borderColor(): ColorInput {\n return this._borderColor;\n }\n set borderColor(value: ColorInput) {\n this._borderColor = value;\n this.dataVersion++;\n this.changed.emit(this);\n }\n\n get borderWidth(): number {\n return this._borderWidth;\n }\n set borderWidth(value: number) {\n this._borderWidth = value;\n this.dataVersion++;\n this.changed.emit(this);\n }\n\n get symbol(): PointSymbol {\n return this._symbol;\n }\n set symbol(value: PointSymbol) {\n this._symbol = value;\n this.changed.emit(this);\n }\n\n symbolCode(): number {\n return this._symbol === 'disc' ? 0 : this._symbol === 'ring' ? 1 : 2;\n }\n\n /** Per-point size at index `i`. */\n sizeAt(i: number): number {\n const s = this._size;\n return typeof s === 'number' ? s : s[i];\n }\n\n /** Build the interleaved instance buffer (count × 12 floats) for the GPU. */\n buildInstanceData() {\n const out = new Float32Array(this.count * STRIDE);\n for (let i = 0; i < this.count; i++) {\n const o = i * STRIDE;\n out[o] = this.positions[i * 2];\n out[o + 1] = this.positions[i * 2 + 1];\n out[o + 2] = this.sizeAt(i);\n writeColor(out, o + 3, this._faceColor, i);\n writeColor(out, o + 7, this._borderColor, i);\n out[o + 11] = this._borderWidth;\n }\n return out;\n }\n}\n\nfunction writeColor(out: Float32Array, offset: number, color: ColorInput, i: number): void {\n const c = Array.isArray(color[0]) ? (color as RGBA[])[i] : (color as RGBA);\n out[offset] = c[0];\n out[offset + 1] = c[1];\n out[offset + 2] = c[2];\n out[offset + 3] = c[3];\n}\n\nexport const POINTS_INSTANCE_STRIDE = STRIDE;\n","import { Layer, type BlendMode } from './layer';\n\nexport interface LabelsLayerOptions {\n name?: string;\n /** Highlight this label id when {@link showSelectedOnly} is set. */\n selectedLabel?: number;\n showSelectedOnly?: boolean;\n opacity?: number;\n blending?: BlendMode;\n visible?: boolean;\n scale?: [number, number];\n translate?: [number, number];\n}\n\n/**\n * A segmentation/label layer (the napari Labels analog). `data` is an 8-bit integer label\n * image (ids 0..255; 0 = background/transparent), colored by a cyclic LUT. Sampled with\n * nearest filtering so label edges stay crisp. uint16/uint32 label support is a follow-up.\n */\nexport class LabelsLayer extends Layer {\n readonly kind = 'labels';\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n\n private _selectedLabel: number;\n private _showSelectedOnly: boolean;\n\n constructor(data: Uint8Array, width: number, height: number, opts: LabelsLayerOptions = {}) {\n super({ name: opts.name, scale: opts.scale, translate: opts.translate });\n if (data.length < width * height) {\n throw new Error(`Labels data (${data.length}) smaller than ${width}×${height}.`);\n }\n this.data = data;\n this.width = width;\n this.height = height;\n this._selectedLabel = opts.selectedLabel ?? 0;\n this._showSelectedOnly = opts.showSelectedOnly ?? false;\n this._blending = opts.blending ?? 'translucent';\n if (opts.opacity !== undefined) this._opacity = opts.opacity;\n if (opts.visible !== undefined) this._visible = opts.visible;\n }\n\n get selectedLabel(): number {\n return this._selectedLabel;\n }\n set selectedLabel(value: number) {\n this._selectedLabel = Math.max(0, Math.round(value));\n this.changed.emit(this);\n }\n\n get showSelectedOnly(): boolean {\n return this._showSelectedOnly;\n }\n set showSelectedOnly(value: boolean) {\n this._showSelectedOnly = value;\n this.changed.emit(this);\n }\n\n /** Label id at data pixel `(x, y)`, or 0 (background) if out of bounds. */\n labelAt(x: number, y: number): number {\n const px = Math.floor(x);\n const py = Math.floor(y);\n if (px < 0 || py < 0 || px >= this.width || py >= this.height) return 0;\n return this.data[py * this.width + px];\n }\n}\n","import { Layer, type BlendMode } from './layer';\nimport { Colormap, resolveColormap } from '../color/colormap';\n\nexport type VolumeRendering = 'mip' | 'translucent' | 'iso';\n\nexport interface VolumeLayerOptions {\n name?: string;\n colormap?: Colormap | string;\n /** Normalization window in source-data units (default [0,255] for uint8). */\n contrastLimits?: [number, number];\n gamma?: number;\n rendering?: VolumeRendering;\n /** Iso threshold as a windowed value 0..1 (iso mode). */\n isoThreshold?: number;\n opacity?: number;\n blending?: BlendMode;\n visible?: boolean;\n}\n\n/**\n * A 3D scalar volume (the napari Image-in-3D / volume analog), rendered by fragment\n * raymarching. `data` is an 8-bit scalar field of size `width*height*depth` in x-fastest\n * order. uint16/float volumes are a follow-up. Rendered only when `dims.ndisplay === 3`.\n */\nexport class VolumeLayer extends Layer {\n readonly kind = 'volume';\n readonly width: number;\n readonly height: number;\n readonly depth: number;\n readonly data: Uint8Array;\n\n colormapVersion = 0;\n\n private _colormap: Colormap;\n private _contrastLimits: [number, number];\n private _gamma: number;\n private _rendering: VolumeRendering;\n private _isoThreshold: number;\n\n constructor(\n data: Uint8Array,\n width: number,\n height: number,\n depth: number,\n opts: VolumeLayerOptions = {},\n ) {\n super({ name: opts.name });\n if (data.length < width * height * depth) {\n throw new Error(`Volume data (${data.length}) smaller than ${width}×${height}×${depth}.`);\n }\n this.data = data;\n this.width = width;\n this.height = height;\n this.depth = depth;\n this._colormap = resolveColormap(opts.colormap ?? 'viridis');\n this._contrastLimits = opts.contrastLimits ?? [0, 255];\n this._gamma = opts.gamma ?? 1;\n this._rendering = opts.rendering ?? 'mip';\n this._isoThreshold = opts.isoThreshold ?? 0.5;\n this._blending = opts.blending ?? 'translucent';\n if (opts.opacity !== undefined) this._opacity = opts.opacity;\n if (opts.visible !== undefined) this._visible = opts.visible;\n }\n\n get colormap(): Colormap {\n return this._colormap;\n }\n set colormap(value: Colormap | string) {\n this._colormap = resolveColormap(value);\n this.colormapVersion++;\n this.changed.emit(this);\n }\n\n get contrastLimits(): [number, number] {\n return [this._contrastLimits[0], this._contrastLimits[1]];\n }\n set contrastLimits(value: readonly [number, number]) {\n this._contrastLimits = [value[0], value[1]];\n this.changed.emit(this);\n }\n\n get gamma(): number {\n return this._gamma;\n }\n set gamma(value: number) {\n this._gamma = value > 0 ? value : this._gamma;\n this.changed.emit(this);\n }\n\n get rendering(): VolumeRendering {\n return this._rendering;\n }\n set rendering(value: VolumeRendering) {\n this._rendering = value;\n this.changed.emit(this);\n }\n\n renderingCode(): number {\n return this._rendering === 'mip' ? 0 : this._rendering === 'translucent' ? 1 : 2;\n }\n\n get isoThreshold(): number {\n return this._isoThreshold;\n }\n set isoThreshold(value: number) {\n this._isoThreshold = value;\n this.changed.emit(this);\n }\n}\n","/** Column-major 4×4 matrix (WGSL `mat4x4<f32>` layout): element at row r, col c is `m[c*4 + r]`. */\nexport type Mat4 = Float32Array;\n\nexport function identity(): Mat4 {\n const m = new Float32Array(16);\n m[0] = m[5] = m[10] = m[15] = 1;\n return m;\n}\n\n/** Return `a * b` (apply `b` first, then `a`). */\nexport function multiply(a: Mat4, b: Mat4): Mat4 {\n const out = new Float32Array(16);\n for (let c = 0; c < 4; c++) {\n for (let r = 0; r < 4; r++) {\n let sum = 0;\n for (let k = 0; k < 4; k++) {\n sum += a[k * 4 + r] * b[c * 4 + k];\n }\n out[c * 4 + r] = sum;\n }\n }\n return out;\n}\n\n/** Affine map `(x, y) → (sx·x + tx, sy·y + ty)` in homogeneous form (data → world). */\nexport function scaleTranslate2d(sx: number, sy: number, tx: number, ty: number): Mat4 {\n const m = identity();\n m[0] = sx;\n m[5] = sy;\n m[12] = tx;\n m[13] = ty;\n return m;\n}\n\n/**\n * Orthographic 2D view-projection: world → clip space, centered on `center`, scaled by\n * `zoom` (canvas px per world unit), for a `vw`×`vh` viewport. The Y axis is flipped so that\n * increasing world/data Y points downward on screen (image convention).\n */\nexport type Vec3 = readonly [number, number, number];\n\nexport function scale3d(sx: number, sy: number, sz: number): Mat4 {\n const m = identity();\n m[0] = sx;\n m[5] = sy;\n m[10] = sz;\n return m;\n}\n\nexport function translate3d(tx: number, ty: number, tz: number): Mat4 {\n const m = identity();\n m[12] = tx;\n m[13] = ty;\n m[14] = tz;\n return m;\n}\n\n/** WebGPU-style perspective (clip z in [0,1]). `fovy` in radians. */\nexport function perspective(fovy: number, aspect: number, near: number, far: number): Mat4 {\n const f = 1 / Math.tan(fovy / 2);\n const m = new Float32Array(16);\n m[0] = f / aspect;\n m[5] = f;\n m[10] = far / (near - far);\n m[11] = -1;\n m[14] = (far * near) / (near - far);\n return m;\n}\n\n/** Right-handed view matrix looking from `eye` toward `center` (column-major). */\nexport function lookAt(eye: Vec3, center: Vec3, up: Vec3): Mat4 {\n const fx = center[0] - eye[0];\n const fy = center[1] - eye[1];\n const fz = center[2] - eye[2];\n let rl = 1 / Math.hypot(fx, fy, fz);\n const f: [number, number, number] = [fx * rl, fy * rl, fz * rl];\n // s = f × up\n let sx = f[1] * up[2] - f[2] * up[1];\n let sy = f[2] * up[0] - f[0] * up[2];\n let sz = f[0] * up[1] - f[1] * up[0];\n rl = 1 / Math.hypot(sx, sy, sz);\n sx *= rl;\n sy *= rl;\n sz *= rl;\n // u = s × f\n const ux = sy * f[2] - sz * f[1];\n const uy = sz * f[0] - sx * f[2];\n const uz = sx * f[1] - sy * f[0];\n const m = new Float32Array(16);\n m[0] = sx;\n m[1] = ux;\n m[2] = -f[0];\n m[3] = 0;\n m[4] = sy;\n m[5] = uy;\n m[6] = -f[1];\n m[7] = 0;\n m[8] = sz;\n m[9] = uz;\n m[10] = -f[2];\n m[11] = 0;\n m[12] = -(sx * eye[0] + sy * eye[1] + sz * eye[2]);\n m[13] = -(ux * eye[0] + uy * eye[1] + uz * eye[2]);\n m[14] = f[0] * eye[0] + f[1] * eye[1] + f[2] * eye[2];\n m[15] = 1;\n return m;\n}\n\n/** Inverse of a 4×4 matrix (column-major). Returns the identity if singular. */\nexport function invert(a: Mat4): Mat4 {\n const a00 = a[0],\n a01 = a[1],\n a02 = a[2],\n a03 = a[3];\n const a10 = a[4],\n a11 = a[5],\n a12 = a[6],\n a13 = a[7];\n const a20 = a[8],\n a21 = a[9],\n a22 = a[10],\n a23 = a[11];\n const a30 = a[12],\n a31 = a[13],\n a32 = a[14],\n a33 = a[15];\n const b00 = a00 * a11 - a01 * a10;\n const b01 = a00 * a12 - a02 * a10;\n const b02 = a00 * a13 - a03 * a10;\n const b03 = a01 * a12 - a02 * a11;\n const b04 = a01 * a13 - a03 * a11;\n const b05 = a02 * a13 - a03 * a12;\n const b06 = a20 * a31 - a21 * a30;\n const b07 = a20 * a32 - a22 * a30;\n const b08 = a20 * a33 - a23 * a30;\n const b09 = a21 * a32 - a22 * a31;\n const b10 = a21 * a33 - a23 * a31;\n const b11 = a22 * a33 - a23 * a32;\n const det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n if (!det) return identity();\n const d = 1 / det;\n const out = new Float32Array(16);\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * d;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * d;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * d;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * d;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * d;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * d;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * d;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * d;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * d;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * d;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * d;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * d;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * d;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * d;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * d;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * d;\n return out;\n}\n\nexport function ortho2d(\n center: readonly [number, number],\n zoom: number,\n vw: number,\n vh: number,\n): Mat4 {\n const a = (2 * zoom) / Math.max(vw, 1);\n const b = (2 * zoom) / Math.max(vh, 1);\n const m = new Float32Array(16);\n m[0] = a;\n m[5] = -b;\n m[10] = 1;\n m[15] = 1;\n m[12] = -a * center[0];\n m[13] = b * center[1];\n return m;\n}\n","import type { Colormap } from './colormap';\n\n/** Default LUT resolution: 256 entries, the napari/OpenGL convention. */\nexport const LUT_SIZE = 256;\n\n/**\n * Build an `size`×1 RGBA8 lookup table from a colormap by sampling at evenly spaced\n * positions. Suitable for upload as a `rgba8unorm` texture sampled by the fragment shader.\n * Pure and GPU-free (unit-tested).\n */\nexport function buildLut(colormap: Colormap, size: number = LUT_SIZE) {\n const lut = new Uint8Array(size * 4);\n const last = size - 1;\n for (let i = 0; i < size; i++) {\n const [r, g, b] = colormap.sample(last === 0 ? 0 : i / last);\n const o = i * 4;\n lut[o] = to8(r);\n lut[o + 1] = to8(g);\n lut[o + 2] = to8(b);\n lut[o + 3] = 255;\n }\n return lut;\n}\n\nfunction to8(v: number): number {\n const x = v <= 0 ? 0 : v >= 1 ? 1 : v;\n return Math.round(x * 255);\n}\n","import type { PixelDtype } from '../io/texture-source';\n\n/** How a scalar/RGBA source maps onto a GPU texture (shared by single-image and tiled paths). */\nexport interface FormatPlan {\n format: GPUTextureFormat;\n bytesPerPixel: number;\n /** Whether the texture can be linearly filtered (drives sampler + bind-group layout). */\n filterable: boolean;\n /** Factor applied to contrast limits so they match the shader's sample space. */\n sampleScale: number;\n isRgba: boolean;\n}\n\n/**\n * Pick the texture plan for given channels/dtype. uint8 scalar → `r8unorm`; RGBA(uint8) →\n * `rgba8unorm` (both normalized, so clim scales by 1/255); uint16/float32 scalar → `r32float`\n * with native-unit windowing (clim scale 1), filterable only when `float32Filterable`.\n */\nexport function formatPlanFor(\n channels: 1 | 4,\n dtype: PixelDtype,\n float32Filterable: boolean,\n): FormatPlan {\n if (channels === 4) {\n return {\n format: 'rgba8unorm',\n bytesPerPixel: 4,\n filterable: true,\n sampleScale: 1 / 255,\n isRgba: true,\n };\n }\n if (dtype === 'uint8') {\n return {\n format: 'r8unorm',\n bytesPerPixel: 1,\n filterable: true,\n sampleScale: 1 / 255,\n isRgba: false,\n };\n }\n return {\n format: 'r32float',\n bytesPerPixel: 4,\n filterable: float32Filterable,\n sampleScale: 1,\n isRgba: false,\n };\n}\n\n/** Convert tile/image pixels to the upload representation for `format` (uint16 → float32). */\nexport function toUploadData(\n data: Uint8Array | Uint16Array | Float32Array,\n format: GPUTextureFormat,\n): Uint8Array | Float32Array {\n if (format === 'r32float' && !(data instanceof Float32Array)) {\n return Float32Array.from(data);\n }\n return data as Uint8Array | Float32Array;\n}\n","// Image display pipeline: window → invert → gamma → colormap LUT (scalar), or direct\n// window/gamma (RGBA). Output is premultiplied to match the canvas 'premultiplied' alpha\n// mode. Ported from napari's image display path (see docs/04-wgsl-rendering-plan.md).\nexport const IMAGE_COLORMAP_SHADER = /* wgsl */ `\nstruct U {\n mvp : mat4x4<f32>,\n imageSize : vec2<f32>,\n origin : vec2<f32>, // data-space origin of this quad (0 for a full image; tile origin for tiles)\n params : vec4<f32>, // climLo, climHi, gamma, opacity (clim already normalized to sample space)\n flags : vec4<f32>, // isRgba, invert, 0, 0\n};\n\n@group(0) @binding(0) var<uniform> u : U;\n@group(0) @binding(1) var srcSamp : sampler;\n@group(0) @binding(2) var srcTex : texture_2d<f32>;\n@group(0) @binding(3) var lutSamp : sampler;\n@group(0) @binding(4) var lutTex : texture_2d<f32>;\n\nstruct VSOut {\n @builtin(position) position : vec4<f32>,\n @location(0) uv : vec2<f32>,\n};\n\n@vertex\nfn vs(@builtin(vertex_index) vi : u32) -> VSOut {\n var corners = array<vec2<f32>, 6>(\n vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.0, 1.0),\n vec2<f32>(0.0, 1.0), vec2<f32>(1.0, 0.0), vec2<f32>(1.0, 1.0),\n );\n let c = corners[vi];\n var out : VSOut;\n out.position = u.mvp * vec4<f32>(u.origin + c * u.imageSize, 0.0, 1.0);\n out.uv = c;\n return out;\n}\n\n@fragment\nfn fs(in : VSOut) -> @location(0) vec4<f32> {\n let raw = textureSample(srcTex, srcSamp, in.uv);\n let climLo = u.params.x;\n let climHi = u.params.y;\n let gamma = u.params.z;\n let opacity = u.params.w;\n let denom = max(climHi - climLo, 1e-8);\n\n // Scalar path: window → invert → gamma → LUT.\n var t = clamp((raw.r - climLo) / denom, 0.0, 1.0);\n if (u.flags.y > 0.5) { t = 1.0 - t; }\n t = pow(t, gamma);\n let mapped = textureSample(lutTex, lutSamp, vec2<f32>(t, 0.5)).rgb;\n\n // RGB path: per-channel window → gamma.\n var direct = clamp((raw.rgb - vec3<f32>(climLo)) / vec3<f32>(denom), vec3<f32>(0.0), vec3<f32>(1.0));\n direct = pow(direct, vec3<f32>(gamma));\n\n let isRgba = u.flags.x > 0.5;\n let rgb = select(mapped, direct, isRgba);\n let a = select(opacity, raw.a * opacity, isRgba);\n return vec4<f32>(rgb * a, a);\n}\n`;\n","import type { BlendMode } from '../layers/layer';\n\n/**\n * Map a {@link BlendMode} to a WebGPU blend state for premultiplied-alpha output.\n * `opaque` returns `undefined` (blending disabled).\n */\nexport function blendStateFor(mode: BlendMode): GPUBlendState | undefined {\n switch (mode) {\n case 'opaque':\n return undefined;\n case 'translucent':\n return {\n color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n };\n case 'additive':\n return {\n color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },\n };\n case 'minimum':\n return {\n color: { srcFactor: 'one', dstFactor: 'one', operation: 'min' },\n alpha: { srcFactor: 'one', dstFactor: 'one', operation: 'min' },\n };\n }\n}\n","import type { ImageLayer, Interpolation } from '../layers/image-layer';\nimport type { BlendMode } from '../layers/layer';\nimport { multiply, scaleTranslate2d } from '../math/mat4';\nimport { buildLut, LUT_SIZE } from '../color/lut';\nimport { GRAY } from '../color/colormap';\nimport type { TextureSource } from '../io/texture-source';\nimport type { LayerVisual, RenderView } from './layer-visual';\nimport { formatPlanFor, toUploadData, type FormatPlan } from './format-plan';\nimport { IMAGE_COLORMAP_SHADER } from './image-colormap-shader';\nimport { blendStateFor } from './blend';\n\nconst UNIFORM_FLOATS = 28; // 112 bytes: mat4(16) + vec2+pad(4) + vec4(4) + vec4(4)\nconst UNIFORM_BYTES = UNIFORM_FLOATS * 4;\n\n/** A {@link FormatPlan} plus the bytes to upload (null = external image via copyExternalImage). */\ntype UploadPlan = FormatPlan & { data: Uint8Array | Uint16Array | Float32Array | null };\n\nfunction planUpload(source: TextureSource, float32Filterable: boolean): UploadPlan {\n if (source.kind === 'external') {\n return {\n format: 'rgba8unorm',\n bytesPerPixel: 4,\n filterable: true,\n sampleScale: 1 / 255,\n isRgba: true,\n data: null,\n };\n }\n if (source.kind === 'tiled') {\n throw new Error('ImageVisual does not render tiled sources; use TiledImageVisual.');\n }\n const plan = formatPlanFor(source.channels, source.dtype, float32Filterable);\n return { ...plan, data: toUploadData(source.data, plan.format) };\n}\n\n/**\n * Binds one {@link ImageLayer} to a WebGPU pipeline: uploads the source texture and colormap\n * LUT, and draws the layer each frame with its current display uniforms (the napari\n * `Vispy*Layer` wrapper analog). Supports uint8 (r8unorm/rgba8unorm) and uint16/float32\n * (r32float, native-precision windowing). Uses an explicit bind-group layout so unfilterable\n * float textures render correctly when `float32-filterable` is unavailable.\n */\nexport class ImageVisual implements LayerVisual {\n readonly ndisplay = 2 as 2 | 3;\n private readonly module: GPUShaderModule;\n private readonly uniformBuffer: GPUBuffer;\n private readonly scratch = new Float32Array(UNIFORM_FLOATS);\n private readonly bindGroupLayout: GPUBindGroupLayout;\n private readonly pipelineLayout: GPUPipelineLayout;\n private readonly plan: UploadPlan;\n\n private texture!: GPUTexture;\n private lutTexture!: GPUTexture;\n private srcSampler!: GPUSampler;\n private lutSampler!: GPUSampler;\n private pipeline!: GPURenderPipeline;\n private bindGroup!: GPUBindGroup;\n\n private currentBlend: BlendMode;\n private currentInterp: Interpolation;\n private lutVersion: number;\n\n constructor(\n private readonly device: GPUDevice,\n private readonly format: GPUTextureFormat,\n private readonly layer: ImageLayer,\n opts: { float32Filterable: boolean } = { float32Filterable: false },\n ) {\n this.plan = planUpload(layer.source, opts.float32Filterable);\n this.module = device.createShaderModule({ code: IMAGE_COLORMAP_SHADER });\n this.uniformBuffer = device.createBuffer({\n size: UNIFORM_BYTES,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n this.bindGroupLayout = this.buildBindGroupLayout();\n this.pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] });\n\n this.uploadTexture();\n this.lutTexture = this.createLutTexture();\n this.currentInterp = layer.interpolation;\n this.srcSampler = this.createSrcSampler(layer.interpolation);\n this.lutSampler = device.createSampler({\n magFilter: 'linear',\n minFilter: 'linear',\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n });\n this.currentBlend = layer.blending;\n this.pipeline = this.buildPipeline(layer.blending);\n this.bindGroup = this.buildBindGroup();\n this.lutVersion = layer.colormapVersion;\n }\n\n private buildBindGroupLayout(): GPUBindGroupLayout {\n const f = this.plan.filterable;\n return this.device.createBindGroupLayout({\n entries: [\n {\n binding: 0,\n visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,\n buffer: { type: 'uniform' },\n },\n {\n binding: 1,\n visibility: GPUShaderStage.FRAGMENT,\n sampler: { type: f ? 'filtering' : 'non-filtering' },\n },\n {\n binding: 2,\n visibility: GPUShaderStage.FRAGMENT,\n texture: { sampleType: f ? 'float' : 'unfilterable-float' },\n },\n { binding: 3, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'filtering' } },\n { binding: 4, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: 'float' } },\n ],\n });\n }\n\n private uploadTexture(): void {\n const src = this.layer.source;\n if (src.kind === 'external') {\n this.texture = this.device.createTexture({\n size: [src.width, src.height],\n format: this.plan.format,\n usage:\n GPUTextureUsage.TEXTURE_BINDING |\n GPUTextureUsage.COPY_DST |\n GPUTextureUsage.RENDER_ATTACHMENT,\n });\n this.device.queue.copyExternalImageToTexture(\n { source: src.image },\n { texture: this.texture },\n [src.width, src.height],\n );\n return;\n }\n\n this.texture = this.device.createTexture({\n size: [src.width, src.height],\n format: this.plan.format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n this.device.queue.writeTexture(\n { texture: this.texture },\n this.plan.data as GPUAllowSharedBufferSource,\n { bytesPerRow: src.width * this.plan.bytesPerPixel, rowsPerImage: src.height },\n { width: src.width, height: src.height },\n );\n }\n\n private createLutTexture(): GPUTexture {\n const tex = this.device.createTexture({\n size: [LUT_SIZE, 1],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n this.writeLut(tex);\n return tex;\n }\n\n private writeLut(tex: GPUTexture): void {\n const cmap = this.layer.colormap ?? GRAY;\n this.device.queue.writeTexture(\n { texture: tex },\n buildLut(cmap, LUT_SIZE),\n { bytesPerRow: LUT_SIZE * 4, rowsPerImage: 1 },\n { width: LUT_SIZE, height: 1 },\n );\n }\n\n private createSrcSampler(interp: Interpolation): GPUSampler {\n // Unfilterable float textures must use nearest filtering.\n const filter: GPUFilterMode =\n !this.plan.filterable || interp === 'nearest' ? 'nearest' : 'linear';\n return this.device.createSampler({\n magFilter: filter,\n minFilter: filter,\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n });\n }\n\n private buildPipeline(blend: BlendMode): GPURenderPipeline {\n return this.device.createRenderPipeline({\n layout: this.pipelineLayout,\n vertex: { module: this.module, entryPoint: 'vs' },\n fragment: {\n module: this.module,\n entryPoint: 'fs',\n targets: [{ format: this.format, blend: blendStateFor(blend) }],\n },\n primitive: { topology: 'triangle-list' },\n });\n }\n\n private buildBindGroup(): GPUBindGroup {\n return this.device.createBindGroup({\n layout: this.bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: this.uniformBuffer } },\n { binding: 1, resource: this.srcSampler },\n { binding: 2, resource: this.texture.createView() },\n { binding: 3, resource: this.lutSampler },\n { binding: 4, resource: this.lutTexture.createView() },\n ],\n });\n }\n\n /** Reconcile GPU state with the layer's current properties (cheap; called before draw). */\n sync(): void {\n if (this.layer.blending !== this.currentBlend) {\n this.currentBlend = this.layer.blending;\n this.pipeline = this.buildPipeline(this.currentBlend);\n }\n if (this.layer.interpolation !== this.currentInterp) {\n this.currentInterp = this.layer.interpolation;\n this.srcSampler = this.createSrcSampler(this.currentInterp);\n this.bindGroup = this.buildBindGroup();\n }\n if (this.layer.colormapVersion !== this.lutVersion) {\n this.lutVersion = this.layer.colormapVersion;\n this.writeLut(this.lutTexture); // same texture object → no bind-group rebuild\n }\n }\n\n /** Encode a draw of this layer for the current view. */\n draw(pass: GPURenderPassEncoder, view: RenderView): void {\n const src = this.layer.source;\n const model = scaleTranslate2d(\n this.layer.scale[0],\n this.layer.scale[1],\n this.layer.translate[0],\n this.layer.translate[1],\n );\n const mvp = multiply(view.camera2d.viewProjection(view.vw, view.vh), model);\n\n const s = this.scratch;\n s.set(mvp, 0);\n s[16] = src.width;\n s[17] = src.height;\n s[18] = 0;\n s[19] = 0;\n const [lo, hi] = this.layer.contrastLimits;\n s[20] = lo * this.plan.sampleScale;\n s[21] = hi * this.plan.sampleScale;\n s[22] = this.layer.gamma;\n s[23] = this.layer.opacity;\n s[24] = this.plan.isRgba ? 1 : 0;\n s[25] = this.layer.invert ? 1 : 0;\n s[26] = 0;\n s[27] = 0;\n this.device.queue.writeBuffer(this.uniformBuffer, 0, s);\n\n pass.setPipeline(this.pipeline);\n pass.setBindGroup(0, this.bindGroup);\n pass.draw(6);\n }\n\n dispose(): void {\n this.texture.destroy();\n this.lutTexture.destroy();\n this.uniformBuffer.destroy();\n }\n}\n","/** An axis-aligned rectangle in level-0 (full-resolution) data coordinates. */\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A visible tile plus its rect in level-0 data coordinates (so the camera is uniform). */\nexport interface VisibleTile {\n col: number;\n row: number;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** Downsample factor of a pyramid level (level 0 = 1, level 1 = 2, …). */\nexport function levelScale(level: number): number {\n return 2 ** level;\n}\n\n/** Pixel dimensions of a pyramid level. */\nexport function levelDims(\n width: number,\n height: number,\n level: number,\n): { width: number; height: number } {\n const s = levelScale(level);\n return { width: Math.max(1, Math.ceil(width / s)), height: Math.max(1, Math.ceil(height / s)) };\n}\n\n/** Tile grid (cols × rows) at a level. */\nexport function tileGrid(\n width: number,\n height: number,\n level: number,\n tileSize: number,\n): { cols: number; rows: number } {\n const d = levelDims(width, height, level);\n return { cols: Math.ceil(d.width / tileSize), rows: Math.ceil(d.height / tileSize) };\n}\n\n/**\n * Choose the pyramid level whose texels are ≈1 screen pixel for `zoom` (CSS px per level-0\n * unit). Zoomed in (zoom ≥ 1) → level 0; each halving of zoom steps one level coarser.\n * Clamped to `[0, levels-1]`.\n */\nexport function selectLevel(zoom: number, levels: number): number {\n const raw = Math.floor(Math.log2(1 / Math.max(zoom, 1e-9)));\n return Math.min(levels - 1, Math.max(0, raw));\n}\n\n/** The level-0 data rectangle currently visible for a camera and CSS viewport size. */\nexport function worldViewport(\n centerX: number,\n centerY: number,\n zoom: number,\n vw: number,\n vh: number,\n): Rect {\n const hw = vw / 2 / Math.max(zoom, 1e-9);\n const hh = vh / 2 / Math.max(zoom, 1e-9);\n return { x: centerX - hw, y: centerY - hh, width: 2 * hw, height: 2 * hh };\n}\n\n/**\n * Tiles of `level` that overlap `view` (level-0 coords), with each tile's rect in level-0\n * coords (edge tiles clipped to the image bounds). Empty when the view misses the image.\n */\nexport function visibleTiles(\n view: Rect,\n width: number,\n height: number,\n level: number,\n tileSize: number,\n): VisibleTile[] {\n const tw = tileSize * levelScale(level);\n const { cols, rows } = tileGrid(width, height, level, tileSize);\n\n const x0 = Math.max(0, view.x);\n const y0 = Math.max(0, view.y);\n const x1 = Math.min(width, view.x + view.width);\n const y1 = Math.min(height, view.y + view.height);\n if (x1 <= x0 || y1 <= y0) return [];\n\n const c0 = Math.max(0, Math.floor(x0 / tw));\n const c1 = Math.min(cols - 1, Math.floor((x1 - 1e-6) / tw));\n const r0 = Math.max(0, Math.floor(y0 / tw));\n const r1 = Math.min(rows - 1, Math.floor((y1 - 1e-6) / tw));\n\n const tiles: VisibleTile[] = [];\n for (let row = r0; row <= r1; row++) {\n for (let col = c0; col <= c1; col++) {\n const x = col * tw;\n const y = row * tw;\n tiles.push({ col, row, x, y, w: Math.min(tw, width - x), h: Math.min(tw, height - y) });\n }\n }\n return tiles;\n}\n","/**\n * Bounded least-recently-used cache. Insertion/`get` mark an entry most-recently-used; when\n * size exceeds `capacity` the oldest entries are evicted via `onEvict` (used to destroy GPU\n * textures). Relies on `Map` preserving insertion order.\n */\nexport class LruCache<V> {\n private readonly map = new Map<string, V>();\n\n constructor(\n private readonly capacity: number,\n private readonly onEvict?: (value: V, key: string) => void,\n ) {\n if (capacity < 1) throw new Error('LruCache capacity must be >= 1.');\n }\n\n get size(): number {\n return this.map.size;\n }\n\n has(key: string): boolean {\n return this.map.has(key);\n }\n\n /** Get a value and mark it most-recently-used. */\n get(key: string): V | undefined {\n const value = this.map.get(key);\n if (value === undefined) return undefined;\n this.map.delete(key);\n this.map.set(key, value);\n return value;\n }\n\n /** Insert/update a value (most-recently-used), evicting the oldest beyond capacity. */\n set(key: string, value: V): void {\n if (this.map.has(key)) this.map.delete(key);\n this.map.set(key, value);\n while (this.map.size > this.capacity) {\n const oldest = this.map.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n const evicted = this.map.get(oldest)!;\n this.map.delete(oldest);\n this.onEvict?.(evicted, oldest);\n }\n }\n\n delete(key: string): boolean {\n const value = this.map.get(key);\n if (value === undefined) return false;\n this.map.delete(key);\n this.onEvict?.(value, key);\n return true;\n }\n\n clear(): void {\n for (const [key, value] of this.map) this.onEvict?.(value, key);\n this.map.clear();\n }\n}\n","import type { ImageLayer, Interpolation } from '../layers/image-layer';\nimport type { BlendMode } from '../layers/layer';\nimport type { LayerVisual, RenderView } from './layer-visual';\nimport type { TiledSource } from '../io/texture-source';\nimport { multiply, scaleTranslate2d } from '../math/mat4';\nimport { selectLevel, visibleTiles, worldViewport, type VisibleTile } from '../io/pyramid';\nimport { LruCache } from '../cache/lru';\nimport { buildLut, LUT_SIZE } from '../color/lut';\nimport { GRAY } from '../color/colormap';\nimport { formatPlanFor, toUploadData, type FormatPlan } from './format-plan';\nimport { IMAGE_COLORMAP_SHADER } from './image-colormap-shader';\nimport { blendStateFor } from './blend';\n\nconst UNIFORM_FLOATS = 28;\nconst UNIFORM_BYTES = UNIFORM_FLOATS * 4;\nconst DEFAULT_TILE_CAPACITY = 192;\n\ninterface TileEntry {\n texture: GPUTexture;\n uniformBuffer: GPUBuffer;\n bindGroup: GPUBindGroup;\n}\n\n/**\n * Renders a pyramidal {@link TiledSource}: selects a pyramid level from zoom, draws the\n * visible tiles (fetched lazily and cached on the GPU with LRU eviction), and underlays the\n * coarsest level so pans/zooms never flash blank. Z-scrubbing fetches the new slice's tiles\n * (cache keyed by z, so revisited slices are instant). Mirrors napari's tiled-image path.\n */\nexport class TiledImageVisual implements LayerVisual {\n readonly ndisplay = 2 as 2 | 3;\n private readonly source: TiledSource;\n private readonly plan: FormatPlan;\n private readonly module: GPUShaderModule;\n private readonly bindGroupLayout: GPUBindGroupLayout;\n private readonly pipelineLayout: GPUPipelineLayout;\n private readonly lutTexture: GPUTexture;\n private readonly lutSampler: GPUSampler;\n private readonly scratch = new Float32Array(UNIFORM_FLOATS);\n private readonly cache: LruCache<TileEntry>;\n private readonly pending = new Set<string>();\n\n private srcSampler: GPUSampler;\n private pipeline: GPURenderPipeline;\n private currentBlend: BlendMode;\n private currentInterp: Interpolation;\n private lutVersion: number;\n private disposed = false;\n\n constructor(\n private readonly device: GPUDevice,\n private readonly format: GPUTextureFormat,\n private readonly layer: ImageLayer,\n private readonly opts: { float32Filterable: boolean; onNeedsRedraw: () => void },\n ) {\n if (layer.source.kind !== 'tiled') {\n throw new Error('TiledImageVisual requires a tiled source.');\n }\n this.source = layer.source;\n this.plan = formatPlanFor(this.source.channels, this.source.dtype, opts.float32Filterable);\n\n this.module = device.createShaderModule({ code: IMAGE_COLORMAP_SHADER });\n this.bindGroupLayout = this.buildBindGroupLayout();\n this.pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] });\n\n this.lutSampler = device.createSampler({\n magFilter: 'linear',\n minFilter: 'linear',\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n });\n this.lutTexture = device.createTexture({\n size: [LUT_SIZE, 1],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n this.writeLut();\n this.lutVersion = layer.colormapVersion;\n\n this.currentInterp = layer.interpolation;\n this.srcSampler = this.createSrcSampler(layer.interpolation);\n this.currentBlend = layer.blending;\n this.pipeline = this.buildPipeline(layer.blending);\n\n this.cache = new LruCache<TileEntry>(DEFAULT_TILE_CAPACITY, (entry) => {\n entry.texture.destroy();\n entry.uniformBuffer.destroy();\n });\n }\n\n private buildBindGroupLayout(): GPUBindGroupLayout {\n const f = this.plan.filterable;\n return this.device.createBindGroupLayout({\n entries: [\n {\n binding: 0,\n visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,\n buffer: { type: 'uniform' },\n },\n {\n binding: 1,\n visibility: GPUShaderStage.FRAGMENT,\n sampler: { type: f ? 'filtering' : 'non-filtering' },\n },\n {\n binding: 2,\n visibility: GPUShaderStage.FRAGMENT,\n texture: { sampleType: f ? 'float' : 'unfilterable-float' },\n },\n { binding: 3, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'filtering' } },\n { binding: 4, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: 'float' } },\n ],\n });\n }\n\n private buildPipeline(blend: BlendMode): GPURenderPipeline {\n return this.device.createRenderPipeline({\n layout: this.pipelineLayout,\n vertex: { module: this.module, entryPoint: 'vs' },\n fragment: {\n module: this.module,\n entryPoint: 'fs',\n targets: [{ format: this.format, blend: blendStateFor(blend) }],\n },\n primitive: { topology: 'triangle-list' },\n });\n }\n\n private createSrcSampler(interp: Interpolation): GPUSampler {\n const filter: GPUFilterMode =\n !this.plan.filterable || interp === 'nearest' ? 'nearest' : 'linear';\n return this.device.createSampler({\n magFilter: filter,\n minFilter: filter,\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n });\n }\n\n private writeLut(): void {\n const cmap = this.layer.colormap ?? GRAY;\n this.device.queue.writeTexture(\n { texture: this.lutTexture },\n buildLut(cmap, LUT_SIZE),\n { bytesPerRow: LUT_SIZE * 4, rowsPerImage: 1 },\n { width: LUT_SIZE, height: 1 },\n );\n }\n\n private keyOf(level: number, col: number, row: number, z: number): string {\n return `${z}:${level}:${col}:${row}`;\n }\n\n /** Return a ready tile, or kick an async fetch and return undefined. */\n private ensureTile(level: number, col: number, row: number, z: number): TileEntry | undefined {\n const key = this.keyOf(level, col, row, z);\n const cached = this.cache.get(key);\n if (cached) return cached;\n if (this.pending.has(key)) return undefined;\n\n this.pending.add(key);\n this.source\n .fetchTile({ level, col, row, z })\n .then((chunk) => {\n this.pending.delete(key);\n if (this.disposed) return;\n const texture = this.device.createTexture({\n size: [chunk.width, chunk.height],\n format: this.plan.format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n this.device.queue.writeTexture(\n { texture },\n toUploadData(chunk.data, this.plan.format) as GPUAllowSharedBufferSource,\n { bytesPerRow: chunk.width * this.plan.bytesPerPixel, rowsPerImage: chunk.height },\n { width: chunk.width, height: chunk.height },\n );\n const uniformBuffer = this.device.createBuffer({\n size: UNIFORM_BYTES,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n const bindGroup = this.device.createBindGroup({\n layout: this.bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: uniformBuffer } },\n { binding: 1, resource: this.srcSampler },\n { binding: 2, resource: texture.createView() },\n { binding: 3, resource: this.lutSampler },\n { binding: 4, resource: this.lutTexture.createView() },\n ],\n });\n this.cache.set(key, { texture, uniformBuffer, bindGroup });\n this.opts.onNeedsRedraw();\n })\n .catch(() => this.pending.delete(key));\n return undefined;\n }\n\n private drawTile(\n pass: GPURenderPassEncoder,\n entry: TileEntry,\n mvp: Float32Array,\n tile: VisibleTile,\n ): void {\n const s = this.scratch;\n s.set(mvp, 0);\n s[16] = tile.w;\n s[17] = tile.h;\n s[18] = tile.x;\n s[19] = tile.y;\n const [lo, hi] = this.layer.contrastLimits;\n s[20] = lo * this.plan.sampleScale;\n s[21] = hi * this.plan.sampleScale;\n s[22] = this.layer.gamma;\n s[23] = this.layer.opacity;\n s[24] = this.plan.isRgba ? 1 : 0;\n s[25] = this.layer.invert ? 1 : 0;\n s[26] = 0;\n s[27] = 0;\n this.device.queue.writeBuffer(entry.uniformBuffer, 0, s);\n pass.setBindGroup(0, entry.bindGroup);\n pass.draw(6);\n }\n\n sync(): void {\n if (this.layer.blending !== this.currentBlend) {\n this.currentBlend = this.layer.blending;\n this.pipeline = this.buildPipeline(this.currentBlend);\n }\n if (this.layer.interpolation !== this.currentInterp) {\n this.currentInterp = this.layer.interpolation;\n this.srcSampler = this.createSrcSampler(this.currentInterp);\n this.cache.clear(); // tile bind groups reference the old sampler\n }\n if (this.layer.colormapVersion !== this.lutVersion) {\n this.lutVersion = this.layer.colormapVersion;\n this.writeLut();\n }\n }\n\n draw(pass: GPURenderPassEncoder, rv: RenderView): void {\n const { width, height, tileSize, levels } = this.source;\n const cam = rv.camera2d;\n const z = rv.z;\n const view = worldViewport(cam.center[0], cam.center[1], cam.zoom, rv.vw, rv.vh);\n const target = selectLevel(cam.zoom, levels);\n const mvp = multiply(\n cam.viewProjection(rv.vw, rv.vh),\n scaleTranslate2d(\n this.layer.scale[0],\n this.layer.scale[1],\n this.layer.translate[0],\n this.layer.translate[1],\n ),\n );\n\n pass.setPipeline(this.pipeline);\n\n // Coarse base underlay (skip for additive blending, where double-counting would be wrong).\n const coarse = levels - 1;\n if (this.layer.blending !== 'additive' && target !== coarse) {\n for (const tile of visibleTiles(view, width, height, coarse, tileSize)) {\n const entry = this.ensureTile(coarse, tile.col, tile.row, z);\n if (entry) this.drawTile(pass, entry, mvp, tile);\n }\n }\n\n // Target level: draw ready tiles; kick fetches for the rest.\n for (const tile of visibleTiles(view, width, height, target, tileSize)) {\n const entry = this.ensureTile(target, tile.col, tile.row, z);\n if (entry) this.drawTile(pass, entry, mvp, tile);\n }\n }\n\n dispose(): void {\n this.disposed = true;\n this.cache.clear();\n this.lutTexture.destroy();\n }\n}\n","// Instanced point markers with SDF shapes (disc / ring / square) and an antialiased border.\n// One instanced quad per point; size/colors/borderWidth are per-instance vertex attributes.\n// Premultiplied output for the canvas 'premultiplied' alpha mode.\nexport const POINTS_SHADER = /* wgsl */ `\nstruct U {\n mvp : mat4x4<f32>,\n params : vec4<f32>, // symbolCode (0=disc,1=ring,2=square), opacity, 0, 0\n};\n@group(0) @binding(0) var<uniform> u : U;\n\nstruct VSOut {\n @builtin(position) position : vec4<f32>,\n @location(0) local : vec2<f32>,\n @location(1) face : vec4<f32>,\n @location(2) border : vec4<f32>,\n @location(3) borderFrac : f32,\n};\n\n@vertex\nfn vs(\n @builtin(vertex_index) vi : u32,\n @location(0) pos : vec2<f32>,\n @location(1) size : f32,\n @location(2) face : vec4<f32>,\n @location(3) border : vec4<f32>,\n @location(4) borderWidth : f32,\n) -> VSOut {\n var corners = array<vec2<f32>, 6>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(1.0, -1.0), vec2<f32>(-1.0, 1.0),\n vec2<f32>(-1.0, 1.0), vec2<f32>(1.0, -1.0), vec2<f32>(1.0, 1.0),\n );\n let c = corners[vi];\n let world = pos + c * (size * 0.5);\n var out : VSOut;\n out.position = u.mvp * vec4<f32>(world, 0.0, 1.0);\n out.local = c;\n out.face = face;\n out.border = border;\n out.borderFrac = clamp(borderWidth / max(size, 1e-6), 0.0, 1.0);\n return out;\n}\n\n@fragment\nfn fs(in : VSOut) -> @location(0) vec4<f32> {\n let symbol = u.params.x;\n let opacity = u.params.y;\n var d : f32;\n if (symbol > 1.5) { d = max(abs(in.local.x), abs(in.local.y)); } // square\n else { d = length(in.local); } // disc / ring\n\n let aa = max(fwidth(d), 1e-5);\n let inside = 1.0 - smoothstep(1.0 - aa, 1.0, d);\n if (inside <= 0.0) { discard; }\n\n let borderEdge = 1.0 - in.borderFrac;\n let borderMix = smoothstep(borderEdge - aa, borderEdge, d);\n let rgb = mix(in.face.rgb, in.border.rgb, borderMix);\n var a = mix(in.face.a, in.border.a, borderMix);\n if (symbol > 0.5 && symbol < 1.5) { a = a * borderMix; } // ring: only the border ring shows\n a = a * inside * opacity;\n return vec4<f32>(rgb * a, a);\n}\n`;\n","import type { PointsLayer } from '../layers/points-layer';\nimport { POINTS_INSTANCE_STRIDE } from '../layers/points-layer';\nimport type { BlendMode } from '../layers/layer';\nimport type { LayerVisual, RenderView } from './layer-visual';\nimport { multiply, scaleTranslate2d } from '../math/mat4';\nimport { POINTS_SHADER } from './points-shader';\nimport { blendStateFor } from './blend';\n\nconst STRIDE_BYTES = POINTS_INSTANCE_STRIDE * 4; // 48\nconst UNIFORM_FLOATS = 20; // mat4(16) + vec4(4)\nconst UNIFORM_BYTES = UNIFORM_FLOATS * 4;\n\n/** Renders a {@link PointsLayer} as instanced SDF markers. */\nexport class PointsVisual implements LayerVisual {\n readonly ndisplay = 2 as 2 | 3;\n private readonly module: GPUShaderModule;\n private readonly uniformBuffer: GPUBuffer;\n private readonly scratch = new Float32Array(UNIFORM_FLOATS);\n private instanceBuffer: GPUBuffer | null = null;\n private pipeline: GPURenderPipeline;\n private currentBlend: BlendMode;\n private dataVersion = -1;\n\n constructor(\n private readonly device: GPUDevice,\n private readonly format: GPUTextureFormat,\n private readonly layer: PointsLayer,\n ) {\n this.module = device.createShaderModule({ code: POINTS_SHADER });\n this.uniformBuffer = device.createBuffer({\n size: UNIFORM_BYTES,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n this.currentBlend = layer.blending;\n this.pipeline = this.buildPipeline(layer.blending);\n }\n\n private buildPipeline(blend: BlendMode): GPURenderPipeline {\n return this.device.createRenderPipeline({\n layout: 'auto',\n vertex: {\n module: this.module,\n entryPoint: 'vs',\n buffers: [\n {\n arrayStride: STRIDE_BYTES,\n stepMode: 'instance',\n attributes: [\n { shaderLocation: 0, offset: 0, format: 'float32x2' }, // pos\n { shaderLocation: 1, offset: 8, format: 'float32' }, // size\n { shaderLocation: 2, offset: 12, format: 'float32x4' }, // face\n { shaderLocation: 3, offset: 28, format: 'float32x4' }, // border\n { shaderLocation: 4, offset: 44, format: 'float32' }, // borderWidth\n ],\n },\n ],\n },\n fragment: {\n module: this.module,\n entryPoint: 'fs',\n targets: [{ format: this.format, blend: blendStateFor(blend) }],\n },\n primitive: { topology: 'triangle-list' },\n });\n }\n\n sync(): void {\n if (this.layer.blending !== this.currentBlend) {\n this.currentBlend = this.layer.blending;\n this.pipeline = this.buildPipeline(this.currentBlend);\n }\n if (this.layer.dataVersion !== this.dataVersion || !this.instanceBuffer) {\n this.dataVersion = this.layer.dataVersion;\n this.rebuildInstances();\n }\n }\n\n private rebuildInstances(): void {\n this.instanceBuffer?.destroy();\n if (this.layer.count === 0) {\n this.instanceBuffer = null;\n return;\n }\n const data = this.layer.buildInstanceData();\n this.instanceBuffer = this.device.createBuffer({\n size: data.byteLength,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n this.device.queue.writeBuffer(this.instanceBuffer, 0, data);\n }\n\n draw(pass: GPURenderPassEncoder, view: RenderView): void {\n if (!this.instanceBuffer || this.layer.count === 0) return;\n const mvp = multiply(\n view.camera2d.viewProjection(view.vw, view.vh),\n scaleTranslate2d(\n this.layer.scale[0],\n this.layer.scale[1],\n this.layer.translate[0],\n this.layer.translate[1],\n ),\n );\n const s = this.scratch;\n s.set(mvp, 0);\n s[16] = this.layer.symbolCode();\n s[17] = this.layer.opacity;\n s[18] = 0;\n s[19] = 0;\n this.device.queue.writeBuffer(this.uniformBuffer, 0, s);\n\n const bindGroup = this.device.createBindGroup({\n layout: this.pipeline.getBindGroupLayout(0),\n entries: [{ binding: 0, resource: { buffer: this.uniformBuffer } }],\n });\n pass.setPipeline(this.pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.setVertexBuffer(0, this.instanceBuffer);\n pass.draw(6, this.layer.count);\n }\n\n dispose(): void {\n this.instanceBuffer?.destroy();\n this.uniformBuffer.destroy();\n }\n}\n","/** HSV → linear-ish RGB (all components 0..1). */\nfunction hsvToRgb(h: number, s: number, v: number): [number, number, number] {\n const i = Math.floor(h * 6);\n const f = h * 6 - i;\n const p = v * (1 - s);\n const q = v * (1 - f * s);\n const t = v * (1 - (1 - f) * s);\n switch (i % 6) {\n case 0:\n return [v, t, p];\n case 1:\n return [q, v, p];\n case 2:\n return [p, v, t];\n case 3:\n return [p, q, v];\n case 4:\n return [t, p, v];\n default:\n return [v, p, q];\n }\n}\n\n/**\n * Build a cyclic label color LUT: an `size`×1 RGBA8 table indexed by `labelId % size`. Entry\n * 0 is fully transparent (background); the rest are distinct hues spaced by the golden ratio\n * so adjacent ids contrast. Pure and GPU-free (unit-tested). Mirrors napari's cyclic label\n * colormap.\n */\nexport function buildLabelLut(size = 256) {\n const lut = new Uint8Array(size * 4);\n const golden = 0.618033988749895;\n for (let i = 1; i < size; i++) {\n const hue = (i * golden) % 1;\n const [r, g, b] = hsvToRgb(hue, 0.6, 0.95);\n const o = i * 4;\n lut[o] = Math.round(r * 255);\n lut[o + 1] = Math.round(g * 255);\n lut[o + 2] = Math.round(b * 255);\n lut[o + 3] = 255;\n }\n // Entry 0 (background) stays [0,0,0,0].\n return lut;\n}\n","// Label image display: nearest-sample an 8-bit id texture, look the id up in a cyclic RGBA\n// palette LUT, with background (id 0) transparent and an optional selected-only filter.\nexport const LABELS_SHADER = /* wgsl */ `\nstruct U {\n mvp : mat4x4<f32>,\n imageSize : vec2<f32>,\n origin : vec2<f32>,\n params : vec4<f32>, // selectedLabel, showSelectedOnly, opacity, lutSize\n};\n@group(0) @binding(0) var<uniform> u : U;\n@group(0) @binding(1) var samp : sampler;\n@group(0) @binding(2) var labelTex : texture_2d<f32>;\n@group(0) @binding(3) var lutSamp : sampler;\n@group(0) @binding(4) var lut : texture_2d<f32>;\n\nstruct VSOut {\n @builtin(position) position : vec4<f32>,\n @location(0) uv : vec2<f32>,\n};\n\n@vertex\nfn vs(@builtin(vertex_index) vi : u32) -> VSOut {\n var corners = array<vec2<f32>, 6>(\n vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.0, 1.0),\n vec2<f32>(0.0, 1.0), vec2<f32>(1.0, 0.0), vec2<f32>(1.0, 1.0),\n );\n let c = corners[vi];\n var out : VSOut;\n out.position = u.mvp * vec4<f32>(u.origin + c * u.imageSize, 0.0, 1.0);\n out.uv = c;\n return out;\n}\n\n@fragment\nfn fs(in : VSOut) -> @location(0) vec4<f32> {\n let raw = textureSample(labelTex, samp, in.uv).r;\n let id = round(raw * 255.0);\n let lutSize = u.params.w;\n var rgba = textureSample(lut, lutSamp, vec2<f32>((id + 0.5) / lutSize, 0.5));\n if (u.params.y > 0.5 && abs(id - u.params.x) > 0.5) { rgba.a = 0.0; } // show-selected-only\n let a = rgba.a * u.params.z;\n return vec4<f32>(rgba.rgb * a, a);\n}\n`;\n","import type { LabelsLayer } from '../layers/labels-layer';\nimport type { BlendMode } from '../layers/layer';\nimport type { LayerVisual, RenderView } from './layer-visual';\nimport { multiply, scaleTranslate2d } from '../math/mat4';\nimport { buildLabelLut } from '../color/label-colormap';\nimport { LABELS_SHADER } from './labels-shader';\nimport { blendStateFor } from './blend';\n\nconst LUT_SIZE = 256;\nconst UNIFORM_FLOATS = 24; // mat4(16) + vec2 imageSize + vec2 origin + vec4 params\nconst UNIFORM_BYTES = UNIFORM_FLOATS * 4;\n\n/** Renders a {@link LabelsLayer}: nearest-sampled id texture + cyclic palette LUT. */\nexport class LabelsVisual implements LayerVisual {\n readonly ndisplay = 2 as 2 | 3;\n private readonly module: GPUShaderModule;\n private readonly uniformBuffer: GPUBuffer;\n private readonly scratch = new Float32Array(UNIFORM_FLOATS);\n private readonly texture: GPUTexture;\n private readonly lutTexture: GPUTexture;\n private readonly sampler: GPUSampler;\n private readonly bindGroup: GPUBindGroup;\n private pipeline: GPURenderPipeline;\n private currentBlend: BlendMode;\n\n constructor(\n private readonly device: GPUDevice,\n private readonly format: GPUTextureFormat,\n private readonly layer: LabelsLayer,\n ) {\n this.module = device.createShaderModule({ code: LABELS_SHADER });\n this.uniformBuffer = device.createBuffer({\n size: UNIFORM_BYTES,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n // Label id texture (r8unorm, nearest — ids must not be interpolated).\n this.texture = device.createTexture({\n size: [layer.width, layer.height],\n format: 'r8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture(\n { texture: this.texture },\n layer.data as GPUAllowSharedBufferSource,\n { bytesPerRow: layer.width, rowsPerImage: layer.height },\n { width: layer.width, height: layer.height },\n );\n\n // Cyclic palette LUT.\n this.lutTexture = device.createTexture({\n size: [LUT_SIZE, 1],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture(\n { texture: this.lutTexture },\n buildLabelLut(LUT_SIZE),\n { bytesPerRow: LUT_SIZE * 4, rowsPerImage: 1 },\n { width: LUT_SIZE, height: 1 },\n );\n\n this.sampler = device.createSampler({\n magFilter: 'nearest',\n minFilter: 'nearest',\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n });\n\n this.currentBlend = layer.blending;\n this.pipeline = this.buildPipeline(layer.blending);\n this.bindGroup = device.createBindGroup({\n layout: this.pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: this.uniformBuffer } },\n { binding: 1, resource: this.sampler },\n { binding: 2, resource: this.texture.createView() },\n { binding: 3, resource: this.sampler },\n { binding: 4, resource: this.lutTexture.createView() },\n ],\n });\n }\n\n private buildPipeline(blend: BlendMode): GPURenderPipeline {\n return this.device.createRenderPipeline({\n layout: 'auto',\n vertex: { module: this.module, entryPoint: 'vs' },\n fragment: {\n module: this.module,\n entryPoint: 'fs',\n targets: [{ format: this.format, blend: blendStateFor(blend) }],\n },\n primitive: { topology: 'triangle-list' },\n });\n }\n\n sync(): void {\n if (this.layer.blending !== this.currentBlend) {\n this.currentBlend = this.layer.blending;\n this.pipeline = this.buildPipeline(this.currentBlend);\n // 'auto' layout is stable across blend-only rebuilds, so the bind group stays valid.\n }\n }\n\n draw(pass: GPURenderPassEncoder, view: RenderView): void {\n const mvp = multiply(\n view.camera2d.viewProjection(view.vw, view.vh),\n scaleTranslate2d(\n this.layer.scale[0],\n this.layer.scale[1],\n this.layer.translate[0],\n this.layer.translate[1],\n ),\n );\n const s = this.scratch;\n s.set(mvp, 0);\n s[16] = this.layer.width;\n s[17] = this.layer.height;\n s[18] = 0;\n s[19] = 0;\n s[20] = this.layer.selectedLabel;\n s[21] = this.layer.showSelectedOnly ? 1 : 0;\n s[22] = this.layer.opacity;\n s[23] = LUT_SIZE;\n this.device.queue.writeBuffer(this.uniformBuffer, 0, s);\n\n pass.setPipeline(this.pipeline);\n pass.setBindGroup(0, this.bindGroup);\n pass.draw(6);\n }\n\n dispose(): void {\n this.texture.destroy();\n this.lutTexture.destroy();\n this.uniformBuffer.destroy();\n }\n}\n","// Single-pass fragment raymarch. A fullscreen quad reconstructs, per pixel, the view ray in\n// volume space (via invMVP applied to near/far clip points), intersects the [0,1]^3 box, and\n// marches a 3D texture. Modes: MIP, front-to-back translucent DVR, and iso-surface with a\n// central-difference gradient + lambert shading. Ported from napari's volume path (docs/04).\nexport const VOLUME_SHADER = /* wgsl */ `\nstruct U {\n invMvp : mat4x4<f32>,\n params : vec4<f32>, // climLo, climHi (normalized 0..1), gamma, opacity\n params2 : vec4<f32>, // renderingCode (0=mip,1=translucent,2=iso), isoThreshold, steps, 0\n};\n@group(0) @binding(0) var<uniform> u : U;\n@group(0) @binding(1) var volSamp : sampler;\n@group(0) @binding(2) var volTex : texture_3d<f32>;\n@group(0) @binding(3) var lutSamp : sampler;\n@group(0) @binding(4) var lut : texture_2d<f32>;\n\nstruct VSOut {\n @builtin(position) position : vec4<f32>,\n @location(0) ndc : vec2<f32>,\n};\n\n@vertex\nfn vs(@builtin(vertex_index) vi : u32) -> VSOut {\n var corners = array<vec2<f32>, 6>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(1.0, -1.0), vec2<f32>(-1.0, 1.0),\n vec2<f32>(-1.0, 1.0), vec2<f32>(1.0, -1.0), vec2<f32>(1.0, 1.0),\n );\n let c = corners[vi];\n var out : VSOut;\n out.position = vec4<f32>(c, 0.0, 1.0);\n out.ndc = c;\n return out;\n}\n\nfn unproject(ndc : vec2<f32>, z : f32) -> vec3<f32> {\n let p = u.invMvp * vec4<f32>(ndc, z, 1.0);\n return p.xyz / p.w;\n}\n\nfn sampleWindowed(pos : vec3<f32>) -> f32 {\n let s = textureSampleLevel(volTex, volSamp, pos, 0.0).r;\n let lo = u.params.x;\n let hi = u.params.y;\n let t = clamp((s - lo) / max(hi - lo, 1e-6), 0.0, 1.0);\n return pow(t, u.params.z);\n}\n\nfn lutColor(t : f32) -> vec3<f32> {\n return textureSampleLevel(lut, lutSamp, vec2<f32>(clamp(t, 0.0, 1.0), 0.5), 0.0).rgb;\n}\n\n@fragment\nfn fs(in : VSOut) -> @location(0) vec4<f32> {\n let ro = unproject(in.ndc, 0.0); // near point, volume space\n let rf = unproject(in.ndc, 1.0); // far point\n let rd = rf - ro;\n\n // Intersect ray with the unit box [0,1]^3 (parameter t along rd).\n let inv = 1.0 / rd;\n let t0 = (vec3<f32>(0.0) - ro) * inv;\n let t1 = (vec3<f32>(1.0) - ro) * inv;\n let tmin = min(t0, t1);\n let tmax = max(t0, t1);\n let tNear = max(max(max(tmin.x, tmin.y), tmin.z), 0.0);\n let tFar = min(min(tmax.x, tmax.y), 1.0 * min(tmax.z, 1.0e9));\n if (tFar <= tNear) { discard; }\n\n let steps = i32(u.params2.z);\n let dt = (tFar - tNear) / f32(steps);\n let mode = u.params2.x;\n let opacity = u.params.w;\n\n var maxT = 0.0;\n var col = vec3<f32>(0.0);\n var acc = 0.0;\n\n for (var i = 0; i < steps; i = i + 1) {\n let t = tNear + (f32(i) + 0.5) * dt;\n let pos = ro + rd * t;\n let w = sampleWindowed(pos);\n\n if (mode < 0.5) {\n // MIP\n maxT = max(maxT, w);\n } else if (mode < 1.5) {\n // Front-to-back translucent DVR\n let a = w * opacity;\n let c = lutColor(w);\n col = col + (1.0 - acc) * c * a;\n acc = acc + (1.0 - acc) * a;\n if (acc >= 0.99) { break; }\n } else {\n // Iso-surface: first crossing → gradient + lambert\n if (w >= u.params2.y) {\n let e = 1.0 / 128.0;\n let gx = sampleWindowed(pos + vec3<f32>(e, 0.0, 0.0)) - sampleWindowed(pos - vec3<f32>(e, 0.0, 0.0));\n let gy = sampleWindowed(pos + vec3<f32>(0.0, e, 0.0)) - sampleWindowed(pos - vec3<f32>(0.0, e, 0.0));\n let gz = sampleWindowed(pos + vec3<f32>(0.0, 0.0, e)) - sampleWindowed(pos - vec3<f32>(0.0, 0.0, e));\n let n = normalize(vec3<f32>(gx, gy, gz) + vec3<f32>(1e-5));\n let lightDir = normalize(vec3<f32>(0.5, 0.7, 1.0));\n let lambert = max(dot(n, lightDir), 0.0) * 0.8 + 0.2;\n col = lutColor(w) * lambert;\n acc = opacity;\n break;\n }\n }\n }\n\n if (mode < 0.5) {\n if (maxT <= 0.0) { discard; }\n col = lutColor(maxT);\n acc = opacity;\n }\n if (acc <= 0.0) { discard; }\n return vec4<f32>(col * acc, acc);\n}\n`;\n","import type { VolumeLayer } from '../layers/volume-layer';\nimport type { BlendMode } from '../layers/layer';\nimport type { LayerVisual, RenderView } from './layer-visual';\nimport { multiply, scale3d, translate3d, invert } from '../math/mat4';\nimport { buildLut, LUT_SIZE } from '../color/lut';\nimport { VOLUME_SHADER } from './volume-shader';\nimport { blendStateFor } from './blend';\n\nconst UNIFORM_FLOATS = 24; // mat4(16) + vec4 params + vec4 params2\nconst UNIFORM_BYTES = UNIFORM_FLOATS * 4;\nconst STEPS = 192;\n\n/**\n * Renders a {@link VolumeLayer} by fragment raymarching a 3D texture (see volume-shader.ts).\n * Builds `invMVP` (clip → volume [0,1]^3 space) each frame from the 3D camera and a model that\n * centers the `[w,h,d]` box at the origin. NJ-5+ uploads uint8 volumes (r8unorm 3D).\n */\nexport class VolumeVisual implements LayerVisual {\n readonly ndisplay = 3 as 2 | 3;\n\n private readonly module: GPUShaderModule;\n private readonly uniformBuffer: GPUBuffer;\n private readonly scratch = new Float32Array(UNIFORM_FLOATS);\n private readonly texture: GPUTexture;\n private readonly lutTexture: GPUTexture;\n private readonly volSampler: GPUSampler;\n private readonly lutSampler: GPUSampler;\n private readonly model: Float32Array;\n private bindGroup: GPUBindGroup;\n private pipeline: GPURenderPipeline;\n private currentBlend: BlendMode;\n private lutVersion: number;\n\n constructor(\n private readonly device: GPUDevice,\n private readonly format: GPUTextureFormat,\n private readonly layer: VolumeLayer,\n ) {\n this.module = device.createShaderModule({ code: VOLUME_SHADER });\n this.uniformBuffer = device.createBuffer({\n size: UNIFORM_BYTES,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n this.texture = device.createTexture({\n size: [layer.width, layer.height, layer.depth],\n dimension: '3d',\n format: 'r8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture(\n { texture: this.texture },\n layer.data as GPUAllowSharedBufferSource,\n { bytesPerRow: layer.width, rowsPerImage: layer.height },\n { width: layer.width, height: layer.height, depthOrArrayLayers: layer.depth },\n );\n\n this.lutTexture = device.createTexture({\n size: [LUT_SIZE, 1],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n this.writeLut();\n this.lutVersion = layer.colormapVersion;\n\n this.volSampler = device.createSampler({\n magFilter: 'linear',\n minFilter: 'linear',\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n addressModeW: 'clamp-to-edge',\n });\n this.lutSampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' });\n\n // Model: map volume [0,1]^3 → world box centered at origin, sized by voxel dims.\n this.model = multiply(\n scale3d(layer.width, layer.height, layer.depth),\n translate3d(-0.5, -0.5, -0.5),\n );\n\n this.currentBlend = layer.blending;\n this.pipeline = this.buildPipeline(layer.blending);\n this.bindGroup = this.buildBindGroup();\n }\n\n private buildPipeline(blend: BlendMode): GPURenderPipeline {\n return this.device.createRenderPipeline({\n layout: 'auto',\n vertex: { module: this.module, entryPoint: 'vs' },\n fragment: {\n module: this.module,\n entryPoint: 'fs',\n targets: [{ format: this.format, blend: blendStateFor(blend) }],\n },\n primitive: { topology: 'triangle-list' },\n });\n }\n\n private buildBindGroup(): GPUBindGroup {\n return this.device.createBindGroup({\n layout: this.pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: this.uniformBuffer } },\n { binding: 1, resource: this.volSampler },\n { binding: 2, resource: this.texture.createView() },\n { binding: 3, resource: this.lutSampler },\n { binding: 4, resource: this.lutTexture.createView() },\n ],\n });\n }\n\n private writeLut(): void {\n this.device.queue.writeTexture(\n { texture: this.lutTexture },\n buildLut(this.layer.colormap, LUT_SIZE),\n { bytesPerRow: LUT_SIZE * 4, rowsPerImage: 1 },\n { width: LUT_SIZE, height: 1 },\n );\n }\n\n sync(): void {\n if (this.layer.blending !== this.currentBlend) {\n this.currentBlend = this.layer.blending;\n this.pipeline = this.buildPipeline(this.currentBlend);\n this.bindGroup = this.buildBindGroup();\n }\n if (this.layer.colormapVersion !== this.lutVersion) {\n this.lutVersion = this.layer.colormapVersion;\n this.writeLut();\n }\n }\n\n draw(pass: GPURenderPassEncoder, view: RenderView): void {\n const mvp = multiply(view.camera3d.viewProjection(view.vw, view.vh), this.model);\n const invMvp = invert(mvp);\n\n const s = this.scratch;\n s.set(invMvp, 0);\n const [lo, hi] = this.layer.contrastLimits;\n s[16] = lo / 255;\n s[17] = hi / 255;\n s[18] = this.layer.gamma;\n s[19] = this.layer.opacity;\n s[20] = this.layer.renderingCode();\n s[21] = this.layer.isoThreshold;\n s[22] = STEPS;\n s[23] = 0;\n this.device.queue.writeBuffer(this.uniformBuffer, 0, s);\n\n pass.setPipeline(this.pipeline);\n pass.setBindGroup(0, this.bindGroup);\n pass.draw(6);\n }\n\n dispose(): void {\n this.texture.destroy();\n this.lutTexture.destroy();\n this.uniformBuffer.destroy();\n }\n}\n","import type { CanvasTarget } from './canvas';\nimport type { Camera } from '../camera/camera';\nimport type { Camera3D } from '../camera/camera3d';\nimport type { Layer } from '../layers/layer';\nimport { ImageLayer } from '../layers/image-layer';\nimport { PointsLayer } from '../layers/points-layer';\nimport { LabelsLayer } from '../layers/labels-layer';\nimport { VolumeLayer } from '../layers/volume-layer';\nimport { ImageVisual } from '../visuals/image-visual';\nimport { TiledImageVisual } from '../visuals/tiled-image-visual';\nimport { PointsVisual } from '../visuals/points-visual';\nimport { LabelsVisual } from '../visuals/labels-visual';\nimport { VolumeVisual } from '../visuals/volume-visual';\nimport type { LayerVisual, RenderView } from '../visuals/layer-visual';\n\n/** Camera/dims inputs the viewer hands to a render call (viewport size is filled internally). */\nexport interface RenderInputs {\n camera2d: Camera;\n camera3d: Camera3D;\n ndisplay: 2 | 3;\n z: number;\n}\n\nexport interface RendererOptions {\n float32Filterable: boolean;\n /** Called when an async tile upload completes, so the host can schedule a redraw. */\n onNeedsRedraw: () => void;\n}\n\n/**\n * Scene renderer: owns one {@link LayerVisual} per layer (a single-image or tiled visual,\n * chosen by source kind) and draws them in order each frame. Layer lifecycle is driven by\n * the {@link Viewer}; this class only uploads, syncs, and draws.\n */\nexport class Renderer {\n private readonly visuals = new Map<string, LayerVisual>();\n\n constructor(\n private readonly device: GPUDevice,\n private readonly target: CanvasTarget,\n private readonly options: RendererOptions = {\n float32Filterable: false,\n onNeedsRedraw: () => {},\n },\n ) {}\n\n addLayer(layer: Layer): void {\n if (this.visuals.has(layer.id)) return;\n const visual = this.createVisual(layer);\n if (visual) this.visuals.set(layer.id, visual);\n }\n\n private createVisual(layer: Layer): LayerVisual | null {\n const format = this.target.format;\n if (layer instanceof ImageLayer) {\n return layer.source.kind === 'tiled'\n ? new TiledImageVisual(this.device, format, layer, {\n float32Filterable: this.options.float32Filterable,\n onNeedsRedraw: this.options.onNeedsRedraw,\n })\n : new ImageVisual(this.device, format, layer, {\n float32Filterable: this.options.float32Filterable,\n });\n }\n if (layer instanceof PointsLayer) return new PointsVisual(this.device, format, layer);\n if (layer instanceof LabelsLayer) return new LabelsVisual(this.device, format, layer);\n if (layer instanceof VolumeLayer) return new VolumeVisual(this.device, format, layer);\n return null;\n }\n\n removeLayer(id: string): void {\n this.visuals.get(id)?.dispose();\n this.visuals.delete(id);\n }\n\n has(id: string): boolean {\n return this.visuals.has(id);\n }\n\n /** Draw the given layers (in order) into the swapchain for the current cameras/dims. */\n render(\n inputs: RenderInputs,\n layers: readonly Layer[],\n background: GPUColor = { r: 0.07, g: 0.07, b: 0.09, a: 1 },\n ): void {\n const vw = this.target.canvas.clientWidth || this.target.canvas.width;\n const vh = this.target.canvas.clientHeight || this.target.canvas.height;\n this.renderInto(this.target.view, inputs, layers, vw, vh, background);\n }\n\n /**\n * Draw into an arbitrary color-attachment view. `vw`/`vh` are the CSS-pixel projection size\n * (resolution-independent); the attachment may be a different device-pixel size. Only\n * visuals whose `ndisplay` matches `inputs.ndisplay` are drawn. Used for both the swapchain\n * and offscreen readback.\n */\n renderInto(\n view: GPUTextureView,\n inputs: RenderInputs,\n layers: readonly Layer[],\n vw: number,\n vh: number,\n background: GPUColor = { r: 0.07, g: 0.07, b: 0.09, a: 1 },\n ): void {\n const rv: RenderView = {\n camera2d: inputs.camera2d,\n camera3d: inputs.camera3d,\n vw,\n vh,\n z: inputs.z,\n ndisplay: inputs.ndisplay,\n };\n const encoder = this.device.createCommandEncoder();\n const pass = encoder.beginRenderPass({\n colorAttachments: [{ view, clearValue: background, loadOp: 'clear', storeOp: 'store' }],\n });\n for (const layer of layers) {\n if (!layer.visible) continue;\n const visual = this.visuals.get(layer.id);\n if (!visual || visual.ndisplay !== rv.ndisplay) continue;\n visual.sync();\n visual.draw(pass, rv);\n }\n pass.end();\n this.device.queue.submit([encoder.finish()]);\n }\n\n dispose(): void {\n for (const visual of this.visuals.values()) visual.dispose();\n this.visuals.clear();\n }\n}\n","import { Emitter } from './events';\nimport type { Layer } from '../layers/layer';\n\n/** Ordered, evented collection of layers. Index 0 is drawn first (bottom). */\nexport class LayerList implements Iterable<Layer> {\n private readonly _items: Layer[] = [];\n\n readonly added = new Emitter<Layer>();\n readonly removed = new Emitter<Layer>();\n /** Fires on any structural change (add/remove/move/clear). */\n readonly changed = new Emitter<LayerList>();\n\n get items(): readonly Layer[] {\n return this._items;\n }\n\n get length(): number {\n return this._items.length;\n }\n\n add(layer: Layer): Layer {\n this._items.push(layer);\n this.added.emit(layer);\n this.changed.emit(this);\n return layer;\n }\n\n remove(layer: Layer): boolean {\n const i = this._items.indexOf(layer);\n if (i < 0) return false;\n this._items.splice(i, 1);\n this.removed.emit(layer);\n this.changed.emit(this);\n return true;\n }\n\n clear(): void {\n const old = this._items.splice(0, this._items.length);\n for (const layer of old) this.removed.emit(layer);\n this.changed.emit(this);\n }\n\n [Symbol.iterator](): Iterator<Layer> {\n return this._items[Symbol.iterator]();\n }\n}\n","import { Emitter } from './events';\n\n/**\n * Dimension/slicing state. NJ-3 models the displayed 2D plane plus a single steppable\n * Z (stack) axis; the general N-D `currentStep` arrives with higher-dimensional data later.\n * `z` is clamped to `[0, depth-1]`. Mutations emit {@link changed}.\n */\nexport class Dims {\n readonly changed = new Emitter<Dims>();\n\n private _ndisplay: 2 | 3 = 2;\n private _depth = 1;\n private _z = 0;\n\n get ndisplay(): 2 | 3 {\n return this._ndisplay;\n }\n set ndisplay(value: 2 | 3) {\n this._ndisplay = value;\n this.changed.emit(this);\n }\n\n /** Number of z-slices. Setting it re-clamps `z`. */\n get depth(): number {\n return this._depth;\n }\n set depth(value: number) {\n this._depth = Math.max(1, Math.floor(value));\n this._z = clamp(this._z, 0, this._depth - 1);\n this.changed.emit(this);\n }\n\n /** Current z-slice index, clamped to `[0, depth-1]`. */\n get z(): number {\n return this._z;\n }\n set z(value: number) {\n const next = clamp(Math.round(value), 0, this._depth - 1);\n if (next === this._z) return;\n this._z = next;\n this.changed.emit(this);\n }\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n return v < lo ? lo : v > hi ? hi : v;\n}\n","import { Emitter } from '../scene/events';\nimport { ortho2d, type Mat4 } from '../math/mat4';\n\n/**\n * 2D orthographic pan/zoom camera. `center` is in world coordinates; `zoom` is canvas pixels\n * per world unit. Emits {@link changed} on any mutation so the viewer can schedule a redraw.\n * The 3D arcball camera arrives in NJ-5+.\n */\nexport class Camera {\n readonly changed = new Emitter<Camera>();\n\n private _center: [number, number] = [0, 0];\n private _zoom = 1;\n\n get center(): [number, number] {\n return [this._center[0], this._center[1]];\n }\n set center(value: readonly [number, number]) {\n this._center = [value[0], value[1]];\n this.changed.emit(this);\n }\n\n get zoom(): number {\n return this._zoom;\n }\n set zoom(value: number) {\n this._zoom = value > 0 ? value : this._zoom;\n this.changed.emit(this);\n }\n\n /** Set center + zoom in one mutation (single change event). */\n set(center: readonly [number, number], zoom: number): void {\n this._center = [center[0], center[1]];\n if (zoom > 0) this._zoom = zoom;\n this.changed.emit(this);\n }\n\n /** World→clip view-projection matrix for a `vw`×`vh` viewport. */\n viewProjection(vw: number, vh: number): Mat4 {\n return ortho2d(this._center, this._zoom, vw, vh);\n }\n\n /**\n * Frame a `width`×`height` region centered in a `vw`×`vh` viewport (with a little margin),\n * e.g. to fit a freshly loaded image. No-op for degenerate inputs.\n */\n fit(width: number, height: number, vw: number, vh: number, margin = 0.95): void {\n if (width <= 0 || height <= 0 || vw <= 0 || vh <= 0) return;\n const zoom = Math.min(vw / width, vh / height) * margin;\n this.set([width / 2, height / 2], zoom);\n }\n}\n","import { Emitter } from '../scene/events';\nimport { perspective, lookAt, multiply, type Mat4, type Vec3 } from '../math/mat4';\n\nconst HALF_PI = Math.PI / 2;\nconst EPS = 1e-3;\n\n/**\n * Orbit camera for 3D (volume) rendering: spins around `target` at `distance`, parameterized\n * by `azimuth`/`elevation`. Produces a perspective view-projection. Emits {@link changed} on\n * mutation. Used when `dims.ndisplay === 3`.\n */\nexport class Camera3D {\n readonly changed = new Emitter<Camera3D>();\n\n azimuth = 0.7;\n elevation = 0.5;\n fov = (45 * Math.PI) / 180;\n\n private _distance = 3;\n private _target: [number, number, number] = [0, 0, 0];\n\n get distance(): number {\n return this._distance;\n }\n set distance(value: number) {\n this._distance = Math.max(EPS, value);\n this.changed.emit(this);\n }\n\n get target(): [number, number, number] {\n return [...this._target];\n }\n set target(value: Vec3) {\n this._target = [value[0], value[1], value[2]];\n this.changed.emit(this);\n }\n\n /** Rotate the orbit by deltas (radians); elevation is clamped to avoid gimbal flip. */\n orbit(dAzimuth: number, dElevation: number): void {\n this.azimuth += dAzimuth;\n this.elevation = clamp(this.elevation + dElevation, -HALF_PI + EPS, HALF_PI - EPS);\n this.changed.emit(this);\n }\n\n zoomBy(factor: number): void {\n this.distance = this._distance * factor;\n }\n\n /** Eye position in world space. */\n eye(): [number, number, number] {\n const ce = Math.cos(this.elevation);\n return [\n this._target[0] + this._distance * ce * Math.sin(this.azimuth),\n this._target[1] + this._distance * Math.sin(this.elevation),\n this._target[2] + this._distance * ce * Math.cos(this.azimuth),\n ];\n }\n\n /** Perspective view-projection for a `vw`×`vh` viewport. */\n viewProjection(vw: number, vh: number): Mat4 {\n const aspect = vh > 0 ? vw / vh : 1;\n const near = Math.max(EPS, this._distance * 0.05);\n const far = this._distance * 4 + 1;\n const proj = perspective(this.fov, aspect, near, far);\n const view = lookAt(this.eye(), this._target, [0, 1, 0]);\n return multiply(proj, view);\n }\n\n /** Frame a `[w,h,d]` volume centered at the origin. */\n frame(w: number, h: number, d: number): void {\n this._target = [0, 0, 0];\n this.distance = Math.max(w, h, d) * 1.8;\n }\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n return v < lo ? lo : v > hi ? hi : v;\n}\n","import { Emitter } from './events';\nimport { LayerList } from './layer-list';\nimport { Dims } from './dims';\nimport { Camera } from '../camera/camera';\nimport { Camera3D } from '../camera/camera3d';\nimport type { Layer } from '../layers/layer';\n\n/**\n * Headless viewer state: a {@link LayerList} and a {@link Camera}. Render-agnostic and\n * GPU-free, so it can be constructed and unit-tested without WebGPU (the napari\n * `ViewerModel` analog). Emits {@link changed} when the layer list, the camera, or any\n * layer's display properties change — the single signal the renderer listens on.\n */\nexport class ViewerModel {\n readonly layers = new LayerList();\n readonly camera = new Camera();\n readonly camera3d = new Camera3D();\n readonly dims = new Dims();\n readonly changed = new Emitter<ViewerModel>();\n\n private readonly layerDisposers = new Map<Layer, () => void>();\n\n constructor() {\n this.layers.changed.connect(() => this.changed.emit(this));\n this.camera.changed.connect(() => this.changed.emit(this));\n this.camera3d.changed.connect(() => this.changed.emit(this));\n this.dims.changed.connect(() => this.changed.emit(this));\n this.layers.added.connect((layer) => {\n this.layerDisposers.set(\n layer,\n layer.changed.connect(() => this.changed.emit(this)),\n );\n });\n this.layers.removed.connect((layer) => {\n this.layerDisposers.get(layer)?.();\n this.layerDisposers.delete(layer);\n });\n }\n}\n","import type { Camera } from './camera';\n\n/**\n * Attach pointer-drag panning and wheel zoom (zoom about the cursor) to a canvas. Returns a\n * detach function. World/screen conversion uses the camera's current center+zoom and the\n * canvas's CSS size (Y flipped to match {@link ortho2d}).\n */\nexport function attachCameraControls(canvas: HTMLCanvasElement, camera: Camera): () => void {\n let dragging = false;\n let lastX = 0;\n let lastY = 0;\n\n const onPointerDown = (e: PointerEvent): void => {\n dragging = true;\n lastX = e.clientX;\n lastY = e.clientY;\n canvas.setPointerCapture(e.pointerId);\n };\n\n const onPointerMove = (e: PointerEvent): void => {\n if (!dragging) return;\n const dxPx = e.clientX - lastX;\n const dyPx = e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n // Drag right → content moves right → center moves left. Y axis is flipped on screen.\n const { zoom } = camera;\n const [cx, cy] = camera.center;\n camera.center = [cx - dxPx / zoom, cy - dyPx / zoom];\n };\n\n const onPointerUp = (e: PointerEvent): void => {\n dragging = false;\n if (canvas.hasPointerCapture(e.pointerId)) {\n canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault();\n const rect = canvas.getBoundingClientRect();\n // Cursor in CSS pixels relative to canvas center.\n const px = e.clientX - rect.left - rect.width / 2;\n const py = e.clientY - rect.top - rect.height / 2;\n const { zoom } = camera;\n const [cx, cy] = camera.center;\n // World point under the cursor before zoom.\n const wx = cx + px / zoom;\n const wy = cy + py / zoom;\n const factor = Math.exp(-e.deltaY * 0.0015);\n const newZoom = zoom * factor;\n // Keep that world point under the cursor after zoom.\n camera.set([wx - px / newZoom, wy - py / newZoom], newZoom);\n };\n\n canvas.addEventListener('pointerdown', onPointerDown);\n canvas.addEventListener('pointermove', onPointerMove);\n canvas.addEventListener('pointerup', onPointerUp);\n canvas.addEventListener('pointercancel', onPointerUp);\n canvas.addEventListener('wheel', onWheel, { passive: false });\n\n return () => {\n canvas.removeEventListener('pointerdown', onPointerDown);\n canvas.removeEventListener('pointermove', onPointerMove);\n canvas.removeEventListener('pointerup', onPointerUp);\n canvas.removeEventListener('pointercancel', onPointerUp);\n canvas.removeEventListener('wheel', onWheel);\n };\n}\n","import type { Camera3D } from './camera3d';\n\n/**\n * Attach orbit controls to a canvas: drag rotates (azimuth/elevation), wheel dollies in/out.\n * Returns a detach function.\n */\nexport function attachOrbitControls(canvas: HTMLCanvasElement, camera: Camera3D): () => void {\n let dragging = false;\n let lastX = 0;\n let lastY = 0;\n\n const onPointerDown = (e: PointerEvent): void => {\n dragging = true;\n lastX = e.clientX;\n lastY = e.clientY;\n canvas.setPointerCapture(e.pointerId);\n };\n\n const onPointerMove = (e: PointerEvent): void => {\n if (!dragging) return;\n const dx = e.clientX - lastX;\n const dy = e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n camera.orbit(-dx * 0.01, -dy * 0.01);\n };\n\n const onPointerUp = (e: PointerEvent): void => {\n dragging = false;\n if (canvas.hasPointerCapture(e.pointerId)) canvas.releasePointerCapture(e.pointerId);\n };\n\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault();\n camera.zoomBy(Math.exp(e.deltaY * 0.0015));\n };\n\n canvas.addEventListener('pointerdown', onPointerDown);\n canvas.addEventListener('pointermove', onPointerMove);\n canvas.addEventListener('pointerup', onPointerUp);\n canvas.addEventListener('pointercancel', onPointerUp);\n canvas.addEventListener('wheel', onWheel, { passive: false });\n\n return () => {\n canvas.removeEventListener('pointerdown', onPointerDown);\n canvas.removeEventListener('pointermove', onPointerMove);\n canvas.removeEventListener('pointerup', onPointerUp);\n canvas.removeEventListener('pointercancel', onPointerUp);\n canvas.removeEventListener('wheel', onWheel);\n };\n}\n","/** Composited pixels read back from the GPU (RGBA8, top row first). */\nexport interface PixelData {\n width: number;\n height: number;\n channels: number;\n data: Uint8ClampedArray;\n}\n\nfunction align256(n: number): number {\n return Math.ceil(n / 256) * 256;\n}\n\n/**\n * Copy an `rgba8unorm` texture to the CPU as tightly-packed RGBA bytes. Handles WebGPU's\n * 256-byte `bytesPerRow` alignment by unpadding each row. The texture must have been created\n * with `COPY_SRC` usage.\n */\nexport async function readTextureToRGBA(\n device: GPUDevice,\n texture: GPUTexture,\n width: number,\n height: number,\n): Promise<Uint8ClampedArray> {\n const unpaddedBytesPerRow = width * 4;\n const bytesPerRow = align256(unpaddedBytesPerRow);\n const buffer = device.createBuffer({\n size: bytesPerRow * height,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,\n });\n\n const encoder = device.createCommandEncoder();\n encoder.copyTextureToBuffer(\n { texture },\n { buffer, bytesPerRow, rowsPerImage: height },\n { width, height },\n );\n device.queue.submit([encoder.finish()]);\n\n await buffer.mapAsync(GPUMapMode.READ);\n const padded = new Uint8Array(buffer.getMappedRange());\n const out = new Uint8ClampedArray(unpaddedBytesPerRow * height);\n for (let y = 0; y < height; y++) {\n const srcStart = y * bytesPerRow;\n out.set(padded.subarray(srcStart, srcStart + unpaddedBytesPerRow), y * unpaddedBytesPerRow);\n }\n buffer.unmap();\n buffer.destroy();\n return out;\n}\n","/** A binned intensity histogram over a value range. */\nexport interface Histogram {\n counts: Uint32Array;\n bins: number;\n min: number;\n max: number;\n}\n\n/** Rec.601 luma of an 8-bit RGB triple (0..255). */\nexport function luminance8(r: number, g: number, b: number): number {\n return 0.299 * r + 0.587 * g + 0.114 * b;\n}\n\n/**\n * Histogram of per-pixel luminance over RGBA8 data (alpha ignored), `bins` bins across the\n * 0..255 range. Pure and GPU-free (unit-tested); the viewer feeds it readback pixels.\n */\nexport function histogramRGBA(data: Uint8ClampedArray | Uint8Array, bins: number): Histogram {\n if (bins < 1) throw new Error('histogram bins must be >= 1.');\n const counts = new Uint32Array(bins);\n const scale = bins / 256;\n for (let i = 0; i + 3 < data.length; i += 4) {\n const l = luminance8(data[i], data[i + 1], data[i + 2]);\n let b = Math.floor(l * scale);\n if (b >= bins) b = bins - 1;\n else if (b < 0) b = 0;\n counts[b]++;\n }\n return { counts, bins, min: 0, max: 255 };\n}\n","import { acquireDevice, type DeviceContext } from './engine/device';\nimport { CanvasTarget } from './engine/canvas';\nimport { Renderer } from './engine/renderer';\nimport { ViewerModel } from './scene/viewer-model';\nimport type { Camera } from './camera/camera';\nimport type { LayerList } from './scene/layer-list';\nimport { attachCameraControls } from './camera/controls';\nimport { ImageLayer, type ImageLayerOptions } from './layers/image-layer';\nimport { PointsLayer, type PointsLayerOptions } from './layers/points-layer';\nimport { LabelsLayer, type LabelsLayerOptions } from './layers/labels-layer';\nimport { VolumeLayer, type VolumeLayerOptions } from './layers/volume-layer';\nimport type { Layer } from './layers/layer';\nimport { toTextureSource, depthOf, type ImageInput } from './io/texture-source';\nimport type { Dims } from './scene/dims';\nimport type { Camera3D } from './camera/camera3d';\nimport { attachOrbitControls } from './camera/controls3d';\nimport { readTextureToRGBA, type PixelData } from './engine/readback';\nimport { histogramRGBA, type Histogram } from './color/histogram';\nimport type { RenderInputs } from './engine/renderer';\n\nexport interface ViewerOptions {\n canvas: HTMLCanvasElement;\n /** Background clear color (RGBA 0..1). */\n background?: GPUColor;\n /** Attach pointer/wheel pan-zoom controls (default true). */\n controls?: boolean;\n}\n\n/**\n * The napari-js viewer: a headless {@link ViewerModel} (layers + camera) plus a WebGPU\n * renderer. Construction kicks off async device acquisition — await {@link ready} before\n * the first render. Adding layers / mutating display props schedules a coalesced redraw.\n */\nexport class Viewer {\n readonly ready: Promise<void>;\n readonly model = new ViewerModel();\n\n private readonly canvas: HTMLCanvasElement;\n private readonly background: GPUColor;\n private readonly useControls: boolean;\n\n private ctx?: DeviceContext;\n private target?: CanvasTarget;\n private renderer?: Renderer;\n private detachControls?: () => void;\n private lastControlsNdisplay?: 2 | 3;\n private frameScheduled = false;\n private firstImageFitted = false;\n\n constructor(options: ViewerOptions) {\n this.canvas = options.canvas;\n this.background = options.background ?? { r: 0.07, g: 0.07, b: 0.09, a: 1 };\n this.useControls = options.controls ?? true;\n this.ready = this.init();\n }\n\n get camera(): Camera {\n return this.model.camera;\n }\n\n get layers(): LayerList {\n return this.model.layers;\n }\n\n get dims(): Dims {\n return this.model.dims;\n }\n\n get camera3d(): Camera3D {\n return this.model.camera3d;\n }\n\n get device(): GPUDevice | undefined {\n return this.ctx?.device;\n }\n\n private async init(): Promise<void> {\n this.ctx = await acquireDevice();\n this.target = new CanvasTarget(this.canvas, this.ctx.device);\n this.target.syncSize();\n this.renderer = new Renderer(this.ctx.device, this.target, {\n float32Filterable: this.ctx.features.float32Filterable,\n onNeedsRedraw: () => this.requestRender(),\n });\n\n // Register any layers added before the device was ready.\n for (const layer of this.model.layers) {\n this.renderer.addLayer(layer);\n }\n this.model.layers.added.connect((layer) => {\n this.renderer?.addLayer(layer);\n this.requestRender();\n });\n this.model.layers.removed.connect((layer) => {\n this.renderer?.removeLayer(layer.id);\n this.requestRender();\n });\n this.model.changed.connect(() => this.requestRender());\n\n if (this.useControls) {\n this.installControls();\n this.model.dims.changed.connect(() => this.installControls());\n }\n this.requestRender();\n }\n\n /** Attach the 2D pan/zoom or 3D orbit controls to match `dims.ndisplay`. */\n private installControls(): void {\n const nd = this.model.dims.ndisplay;\n if (nd === this.lastControlsNdisplay) return;\n this.lastControlsNdisplay = nd;\n this.detachControls?.();\n this.detachControls =\n nd === 3\n ? attachOrbitControls(this.canvas, this.model.camera3d)\n : attachCameraControls(this.canvas, this.model.camera);\n }\n\n private renderInputs(): RenderInputs {\n return {\n camera2d: this.model.camera,\n camera3d: this.model.camera3d,\n ndisplay: this.model.dims.ndisplay,\n z: this.model.dims.z,\n };\n }\n\n /** Add an image layer. Accepts typed pixels or a decoded image (see {@link ImageInput}). */\n addImage(input: ImageInput, opts: ImageLayerOptions = {}): ImageLayer {\n const source = toTextureSource(input);\n const layer = new ImageLayer(source, opts);\n this.model.layers.add(layer);\n this.model.dims.depth = Math.max(this.model.dims.depth, depthOf(source));\n this.maybeFitFirst(source.width, source.height);\n return layer;\n }\n\n /** Add a points (scatter) layer. Positions are `[x, y]` pairs in data coordinates. */\n addPoints(positions: Float32Array | number[][], opts: PointsLayerOptions = {}): PointsLayer {\n const layer = new PointsLayer(positions, opts);\n this.model.layers.add(layer);\n return layer;\n }\n\n /** Add a labels (segmentation) layer from an 8-bit id image. */\n addLabels(\n data: Uint8Array,\n width: number,\n height: number,\n opts: LabelsLayerOptions = {},\n ): LabelsLayer {\n const layer = new LabelsLayer(data, width, height, opts);\n this.model.layers.add(layer);\n this.maybeFitFirst(width, height);\n return layer;\n }\n\n /**\n * Add a 3D volume layer (uint8 scalar field, x-fastest). Switches the viewer to 3D\n * (`dims.ndisplay = 3`) and frames the orbit camera on the volume.\n */\n addVolume(\n data: Uint8Array,\n width: number,\n height: number,\n depth: number,\n opts: VolumeLayerOptions = {},\n ): VolumeLayer {\n const layer = new VolumeLayer(data, width, height, depth, opts);\n this.model.layers.add(layer);\n this.model.camera3d.frame(width, height, depth);\n this.model.dims.ndisplay = 3;\n return layer;\n }\n\n /** Convert canvas client coordinates to data/world coordinates (for picking). */\n canvasToWorld(clientX: number, clientY: number): [number, number] {\n const rect = this.canvas.getBoundingClientRect();\n const px = clientX - rect.left - rect.width / 2;\n const py = clientY - rect.top - rect.height / 2;\n const { zoom } = this.model.camera;\n const [cx, cy] = this.model.camera.center;\n return [cx + px / zoom, cy + py / zoom];\n }\n\n private maybeFitFirst(width: number, height: number): void {\n if (this.firstImageFitted) return;\n const vw = this.canvas.clientWidth;\n const vh = this.canvas.clientHeight;\n if (vw > 0 && vh > 0) {\n this.model.camera.fit(width, height, vw, vh);\n this.firstImageFitted = true;\n }\n }\n\n /** Request a coalesced redraw on the next animation frame. No-op until {@link ready}. */\n requestRender(): void {\n if (this.frameScheduled || !this.renderer || !this.target) return;\n this.frameScheduled = true;\n requestAnimationFrame(() => {\n this.frameScheduled = false;\n this.renderFrame();\n });\n }\n\n private renderFrame(): void {\n if (!this.renderer || !this.target) return;\n this.target.syncSize();\n this.renderer.render(this.renderInputs(), this.allLayers(), this.background);\n }\n\n private allLayers(): readonly Layer[] {\n return this.model.layers.items;\n }\n\n /**\n * Read back the composited displayed pixels as RGBA8 (top row first), by rendering the\n * current scene into an offscreen texture at the canvas's device-pixel size.\n */\n async readDisplayedPixels(): Promise<PixelData> {\n if (!this.renderer || !this.target || !this.ctx) {\n throw new Error('Viewer is not ready — await `viewer.ready` first.');\n }\n const w = Math.max(1, this.canvas.width);\n const h = Math.max(1, this.canvas.height);\n const cssW = this.canvas.clientWidth || w;\n const cssH = this.canvas.clientHeight || h;\n const texture = this.ctx.device.createTexture({\n size: [w, h],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,\n });\n this.renderer.renderInto(\n texture.createView(),\n this.renderInputs(),\n this.allLayers(),\n cssW,\n cssH,\n this.background,\n );\n const data = await readTextureToRGBA(this.ctx.device, texture, w, h);\n texture.destroy();\n return { width: w, height: h, channels: 4, data };\n }\n\n /** Composite the displayed image to a PNG `Blob`. */\n async screenshot(): Promise<Blob> {\n const px = await this.readDisplayedPixels();\n if (typeof OffscreenCanvas !== 'undefined') {\n const off = new OffscreenCanvas(px.width, px.height);\n const ctx = off.getContext('2d')!;\n const image = ctx.createImageData(px.width, px.height);\n image.data.set(px.data);\n ctx.putImageData(image, 0, 0);\n return off.convertToBlob({ type: 'image/png' });\n }\n const el = document.createElement('canvas');\n el.width = px.width;\n el.height = px.height;\n const ctx = el.getContext('2d')!;\n const image = ctx.createImageData(px.width, px.height);\n image.data.set(px.data);\n ctx.putImageData(image, 0, 0);\n return new Promise<Blob>((resolve, reject) => {\n el.toBlob((b) => (b ? resolve(b) : reject(new Error('toBlob returned null'))), 'image/png');\n });\n }\n\n /** Luminance histogram (over `bins` bins) of the currently displayed composite. */\n async histogram(bins = 256): Promise<Histogram> {\n const px = await this.readDisplayedPixels();\n return histogramRGBA(px.data, bins);\n }\n\n dispose(): void {\n this.detachControls?.();\n this.renderer?.dispose();\n this.ctx?.device.destroy();\n this.ctx = undefined;\n this.target = undefined;\n this.renderer = undefined;\n }\n}\n","/**\n * Index of the point whose marker contains `(x, y)` (data coords), nearest center wins, or\n * -1 if none. `sizeAt(i)` returns marker diameter in data units. Pure and GPU-free — the CPU\n * hit-test for point picking (GPU id-buffer picking can come later if needed).\n */\nexport function nearestPointIndex(\n positions: Float32Array,\n sizeAt: (i: number) => number,\n x: number,\n y: number,\n): number {\n let best = -1;\n let bestD2 = Infinity;\n const n = positions.length >> 1;\n for (let i = 0; i < n; i++) {\n const dx = positions[i * 2] - x;\n const dy = positions[i * 2 + 1] - y;\n const d2 = dx * dx + dy * dy;\n const r = sizeAt(i) / 2;\n if (d2 <= r * r && d2 < bestD2) {\n bestD2 = d2;\n best = i;\n }\n }\n return best;\n}\n","import type { Colormap, RGB } from './colormap';\n\n/**\n * CPU reference for the scalar display math the `image-colormap` WGSL shader performs:\n * window → invert → gamma. Returns the normalized LUT coordinate `t` in 0..1. Kept pure and\n * tested so the shader has a ground truth (see docs/04) and so histograms/readback can reuse\n * the exact same math. `value` and the clim are in the same units.\n */\nexport function windowGamma(\n value: number,\n climLo: number,\n climHi: number,\n gamma: number,\n invert: boolean,\n): number {\n const denom = Math.max(climHi - climLo, 1e-8);\n let t = clamp01((value - climLo) / denom);\n if (invert) t = 1 - t;\n return Math.pow(t, gamma);\n}\n\n/** Map a scalar value through window/gamma and a colormap to linear RGB. */\nexport function mapScalar(\n value: number,\n opts: { climLo: number; climHi: number; gamma: number; invert: boolean; colormap: Colormap },\n): RGB {\n return opts.colormap.sample(\n windowGamma(value, opts.climLo, opts.climHi, opts.gamma, opts.invert),\n );\n}\n\n/**\n * Additive composite of premultiplied RGB contributions (channels with `blending: 'additive'`\n * over a black background), clamped to 1 — the CPU reference for multi-channel fluorescence.\n */\nexport function additiveComposite(colors: readonly RGB[]): RGB {\n const out: RGB = [0, 0, 0];\n for (const c of colors) {\n out[0] += c[0];\n out[1] += c[1];\n out[2] += c[2];\n }\n return [clamp01(out[0]), clamp01(out[1]), clamp01(out[2])];\n}\n\nexport function clamp01(x: number): number {\n return x < 0 ? 0 : x > 1 ? 1 : x;\n}\n","export const VERSION = '0.0.0';\n"],"names":["WebGPUUnsupportedError","message","acquireDevice","options","adapter","float32Filterable","requiredFeatures","device","cause","resolveDrawingBufferSize","cssWidth","cssHeight","devicePixelRatio","maxDimension","dpr","clampDim","value","max","CanvasTarget","canvas","format","ctx","maxDim","width","height","Emitter","listener","nextLayerId","Layer","opts","clamp01","v","Colormap","name","stops","p","q","t","x","last","i","hi","lo","span","f","ramp","color","GRAY","RED","GREEN","BLUE","VIRIDIS","MAGMA","NAMED_COLORMAPS","resolveColormap","cmap","found","channelsOf","source","depthOf","isGrayscale","defaultContrastLimits","toTextureSource","input","image","ImageLayer","STRIDE","normalizePositions","positions","out","PointsLayer","s","o","writeColor","offset","c","POINTS_INSTANCE_STRIDE","LabelsLayer","data","y","px","py","VolumeLayer","depth","identity","m","multiply","a","b","r","sum","k","scaleTranslate2d","sx","sy","tx","ty","scale3d","sz","translate3d","tz","perspective","fovy","aspect","near","far","lookAt","eye","center","up","fx","fy","fz","rl","ux","uy","uz","invert","a00","a01","a02","a03","a10","a11","a12","a13","a20","a21","a22","a23","a30","a31","a32","a33","b00","b01","b02","b03","b04","b05","b06","b07","b08","b09","b10","b11","det","d","ortho2d","zoom","vw","vh","LUT_SIZE","buildLut","colormap","size","lut","g","to8","formatPlanFor","channels","dtype","toUploadData","IMAGE_COLORMAP_SHADER","blendStateFor","mode","UNIFORM_FLOATS","UNIFORM_BYTES","planUpload","plan","ImageVisual","layer","src","tex","interp","filter","blend","pass","view","model","mvp","levelScale","level","levelDims","tileGrid","tileSize","selectLevel","levels","raw","worldViewport","centerX","centerY","hw","hh","visibleTiles","tw","cols","rows","x0","y0","x1","y1","c0","c1","r0","r1","tiles","row","col","LruCache","capacity","onEvict","key","oldest","evicted","DEFAULT_TILE_CAPACITY","TiledImageVisual","entry","z","cached","chunk","texture","uniformBuffer","bindGroup","tile","rv","cam","target","coarse","POINTS_SHADER","STRIDE_BYTES","PointsVisual","hsvToRgb","h","buildLabelLut","golden","hue","LABELS_SHADER","LabelsVisual","VOLUME_SHADER","STEPS","VolumeVisual","invMvp","Renderer","visual","id","inputs","layers","background","encoder","LayerList","old","Dims","clamp","next","Camera","margin","HALF_PI","EPS","Camera3D","dAzimuth","dElevation","factor","ce","proj","w","ViewerModel","attachCameraControls","camera","dragging","lastX","lastY","onPointerDown","e","onPointerMove","dxPx","dyPx","cx","cy","onPointerUp","onWheel","rect","wx","wy","newZoom","attachOrbitControls","dx","dy","align256","n","readTextureToRGBA","unpaddedBytesPerRow","bytesPerRow","buffer","padded","srcStart","luminance8","histogramRGBA","bins","counts","scale","l","Viewer","nd","clientX","clientY","cssW","cssH","off","el","resolve","reject","nearestPointIndex","sizeAt","best","bestD2","d2","windowGamma","climLo","climHi","gamma","denom","mapScalar","additiveComposite","colors","VERSION"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Index of the point whose marker contains `(x, y)` (data coords), nearest center wins, or
3
+ * -1 if none. `sizeAt(i)` returns marker diameter in data units. Pure and GPU-free — the CPU
4
+ * hit-test for point picking (GPU id-buffer picking can come later if needed).
5
+ */
6
+ export declare function nearestPointIndex(positions: Float32Array, sizeAt: (i: number) => number, x: number, y: number): number;
@@ -0,0 +1,20 @@
1
+ import { Emitter } from './events';
2
+ /**
3
+ * Dimension/slicing state. NJ-3 models the displayed 2D plane plus a single steppable
4
+ * Z (stack) axis; the general N-D `currentStep` arrives with higher-dimensional data later.
5
+ * `z` is clamped to `[0, depth-1]`. Mutations emit {@link changed}.
6
+ */
7
+ export declare class Dims {
8
+ readonly changed: Emitter<Dims>;
9
+ private _ndisplay;
10
+ private _depth;
11
+ private _z;
12
+ get ndisplay(): 2 | 3;
13
+ set ndisplay(value: 2 | 3);
14
+ /** Number of z-slices. Setting it re-clamps `z`. */
15
+ get depth(): number;
16
+ set depth(value: number);
17
+ /** Current z-slice index, clamped to `[0, depth-1]`. */
18
+ get z(): number;
19
+ set z(value: number);
20
+ }
@@ -0,0 +1,9 @@
1
+ export type Listener<T> = (value: T) => void;
2
+ /** Minimal typed event emitter (the napari `EventEmitter` / psygnal analog). */
3
+ export declare class Emitter<T> {
4
+ private readonly listeners;
5
+ /** Subscribe; returns an unsubscribe function. */
6
+ connect(listener: Listener<T>): () => void;
7
+ emit(value: T): void;
8
+ clear(): void;
9
+ }
@@ -0,0 +1,16 @@
1
+ import { Emitter } from './events';
2
+ import { Layer } from '../layers/layer';
3
+ /** Ordered, evented collection of layers. Index 0 is drawn first (bottom). */
4
+ export declare class LayerList implements Iterable<Layer> {
5
+ private readonly _items;
6
+ readonly added: Emitter<Layer>;
7
+ readonly removed: Emitter<Layer>;
8
+ /** Fires on any structural change (add/remove/move/clear). */
9
+ readonly changed: Emitter<LayerList>;
10
+ get items(): readonly Layer[];
11
+ get length(): number;
12
+ add(layer: Layer): Layer;
13
+ remove(layer: Layer): boolean;
14
+ clear(): void;
15
+ [Symbol.iterator](): Iterator<Layer>;
16
+ }
@@ -0,0 +1,20 @@
1
+ import { Emitter } from './events';
2
+ import { LayerList } from './layer-list';
3
+ import { Dims } from './dims';
4
+ import { Camera } from '../camera/camera';
5
+ import { Camera3D } from '../camera/camera3d';
6
+ /**
7
+ * Headless viewer state: a {@link LayerList} and a {@link Camera}. Render-agnostic and
8
+ * GPU-free, so it can be constructed and unit-tested without WebGPU (the napari
9
+ * `ViewerModel` analog). Emits {@link changed} when the layer list, the camera, or any
10
+ * layer's display properties change — the single signal the renderer listens on.
11
+ */
12
+ export declare class ViewerModel {
13
+ readonly layers: LayerList;
14
+ readonly camera: Camera;
15
+ readonly camera3d: Camera3D;
16
+ readonly dims: Dims;
17
+ readonly changed: Emitter<ViewerModel>;
18
+ private readonly layerDisposers;
19
+ constructor();
20
+ }
@@ -0,0 +1 @@
1
+ export declare const VERSION = "0.0.0";