"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // dist/index.js var dist_exports = {}; __export(dist_exports, { ZarrPixelSource: () => zarr_pixel_source_default, loadZarr: () => loadZarr }); module.exports = __toCommonJS(dist_exports); // dist/lib/utils.js var import_zarr = require("zarr"); function normalizeStore(source) { if (typeof source === "string") { return new import_zarr.HTTPStore(source); } return source; } async function loadMultiscales(store, path = "") { const grp = await (0, import_zarr.openGroup)(store, path); const rootAttrs = await grp.attrs.asObject(); if (!Array.isArray(rootAttrs.multiscales)) { throw new Error("Cannot find Zarr multiscales metadata."); } const { datasets } = rootAttrs.multiscales[0]; const promises = datasets.map((d) => grp.getItem(d.path)); return { data: await Promise.all(promises), rootAttrs }; } function getDims(labels) { const lookup = new Map(labels.map((name, i) => [name, i])); if (lookup.size !== labels.length) { throw Error("Labels must be unique, found duplicated label."); } return (name) => { const index = lookup.get(name); if (index === void 0) { throw Error("Invalid dimension."); } return index; }; } function prevPowerOf2(x) { return 2 ** Math.floor(Math.log2(x)); } function isInterleaved(shape) { const lastDimSize = shape[shape.length - 1]; return lastDimSize === 3 || lastDimSize === 4; } function guessTileSize(arr) { const interleaved = isInterleaved(arr.shape); const [yChunk, xChunk] = arr.chunks.slice(interleaved ? -3 : -2); const size = Math.min(yChunk, xChunk); return prevPowerOf2(size); } function guessLabels(rootAttrs) { if ("omero" in rootAttrs) { return ["t", "c", "z", "y", "x"]; } throw new Error("Could not infer dimension labels for Zarr source. Must provide dimension labels."); } function getIndexer(labels) { const size = labels.length; const dims = getDims(labels); return (sel) => { if (Array.isArray(sel)) { return [...sel]; } const selection = Array(size).fill(0); for (const [key, value] of Object.entries(sel)) { selection[dims(key)] = value; } return selection; }; } function getImageSize(source) { const interleaved = isInterleaved(source.shape); const [height, width] = source.shape.slice(interleaved ? -3 : -2); return { height, width }; } function validLabels(labels, shape) { if (labels.length !== shape.length) { throw new Error("Labels do not match Zarr array shape."); } const n = shape.length; if (isInterleaved(shape)) { return labels[n - 3] === "y" && labels[n - 2] === "x" && labels[n - 1] === "_c"; } return labels[n - 2] === "y" && labels[n - 1] === "x"; } // dist/lib/zarr-pixel-source.js var import_zarr2 = require("zarr"); var DTYPE_LOOKUP = { u1: "Uint8", u2: "Uint16", u4: "Uint32", f4: "Float32", f8: "Float64", i1: "Int8", i2: "Int16", i4: "Int32" }; var ZarrPixelSource = class { labels; tileSize; _data; _indexer; _readChunks; constructor(data, labels, tileSize) { this._indexer = getIndexer(labels); this._data = data; const xChunkSize = data.chunks[this._xIndex]; const yChunkSize = data.chunks[this._xIndex - 1]; this._readChunks = tileSize === xChunkSize && tileSize === yChunkSize; this.labels = labels; this.tileSize = tileSize; } get shape() { return this._data.shape; } get dtype() { const suffix = this._data.dtype.slice(1); if (!(suffix in DTYPE_LOOKUP)) { throw Error(`Zarr dtype not supported, got ${suffix}.`); } return DTYPE_LOOKUP[suffix]; } get _xIndex() { const interleave = isInterleaved(this._data.shape); return this._data.shape.length - (interleave ? 2 : 1); } _chunkIndex(selection, x, y) { const sel = this._indexer(selection); sel[this._xIndex] = x; sel[this._xIndex - 1] = y; return sel; } /** * Converts x, y tile indices to zarr dimension Slices within image bounds. */ _getSlices(x, y) { const { height, width } = getImageSize(this); const [xStart, xStop] = [x * this.tileSize, Math.min((x + 1) * this.tileSize, width)]; const [yStart, yStop] = [y * this.tileSize, Math.min((y + 1) * this.tileSize, height)]; if (xStart === xStop || yStart === yStop) { throw new import_zarr2.BoundsCheckError("Tile slice is zero-sized."); } return [(0, import_zarr2.slice)(xStart, xStop), (0, import_zarr2.slice)(yStart, yStop)]; } async getRaster({ selection }) { const sel = this._chunkIndex(selection, null, null); const { data, shape } = await this._data.getRaw(sel); const [height, width] = shape; return { data, width, height }; } async getTile(props) { const { x, y, selection, signal } = props; let res; if (this._readChunks) { const sel = this._chunkIndex(selection, x, y); res = await this._data.getRawChunk(sel, { storeOptions: { signal } }); } else { const [xSlice, ySlice] = this._getSlices(x, y); const sel = this._chunkIndex(selection, xSlice, ySlice); res = await this._data.getRaw(sel); } const { data, shape: [height, width] } = res; return { data, width, height }; } onTileError(err) { if (!(err instanceof import_zarr2.BoundsCheckError)) { throw err; } } }; var zarr_pixel_source_default = ZarrPixelSource; // dist/lib/load-zarr.js async function loadZarr(root, options = {}) { const store = normalizeStore(root); const { data, rootAttrs } = await loadMultiscales(store); const tileSize = guessTileSize(data[0]); const labels = options.labels ?? guessLabels(rootAttrs); if (!validLabels(labels, data[0].shape)) { throw new Error("Invalid labels for Zarr array dimensions."); } const pyramid = data.map((arr) => new zarr_pixel_source_default(arr, labels, tileSize)); return { data: pyramid, metadata: rootAttrs }; } //# sourceMappingURL=index.cjs.map